# Question
Title: How can you completely remove an old deleted field?
After deploying a Drupal 8 site to a new server, we have the problem of an old deleted field being remembered by some subsystem or other, leading to this error being thrown on whenever cron runs:

```
Drupal\Core\Database\DatabaseExceptionWrapper:
SQLSTATE[42S02]: Base table or view not found:
1146 Table 'drupal8_neu_default.field_deleted_data_1c89727af8' doesn't exist:
SELECT DISTINCT t.entity_id AS entity_id
FROM {field_deleted_data_1c89727af8} t
WHERE  (bundle = :db_condition_placeholder_0)
LIMIT 50 OFFSET 0; Array
(
    [:db_condition_placeholder_0] => video
)
in
Drupal\Core\Entity\Sql\SqlContentEntityStorage->readFieldItemsToPurge()
(line 1546 of /srv/www/neu.default.ch/builds/v1.0.0-alpha.7/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

```

I've spelunked all over the database, and I can't figure out where to expunge the reference to this long-dead table. It's not mentioned in `config` and the `field_config` table we knew from Drupal 7 is long gone. It's also not in the exported configuration.

Does anyone know how to fix this?

# Answer
> 6 votes
This is in the state/key\_value table, with the keys field.field.deleted field.storage.deleted.

To find them, run this sql:

```
select * from key_value where name = "field.field.deleted" or name = "field.storage.deleted"

```

See \Drupal\field\FieldConfigStorage::loadByProperties() and \Drupal\field\FieldStorageConfigStorage::loadByProperties()

# Answer
> 8 votes
Execute this to remove deleted field(s), pending deletion:

```
drush php-eval 'field_purge_batch(1000);'

```

# Answer
> 1 votes
The only way I could resolve this was to create the missing table, for example:

```
CREATE TABLE `field_deleted_data_XXX` (
`bundle` varchar(128) CHARACTER SET ascii NOT NULL DEFAULT '',
`deleted` tinyint(4) NOT NULL DEFAULT '0',
`entity_id` int(10) unsigned NOT NULL,
`revision_id` int(10) unsigned NOT NULL,
`langcode` varchar(32) CHARACTER SET ascii NOT NULL DEFAULT '',
`delta` int(10) unsigned NOT NULL,
`content_translation_source_value` varchar(12) CHARACTER SET ascii NOT NULL,
PRIMARY KEY (`entity_id`,`deleted`,`delta`,`langcode`),
KEY `bundle` (`bundle`),
KEY `revision_id` (`revision_id`) );

```

Replacing `XXX` with the code that follows `field_deleted_data_` in the error message. Then run:

```
drush php-eval 'field_purge_batch(1000);'

```

This may generate the error with a new code. I had to go through the process 3 times, but eventually it resolved the error.

# Answer
> 1 votes
Thank you every one for your answers that allowed me to build the following (imperfect) solution.

List deleted fields waiting to be purged:

```
drush php:eval "var_dump(\Drupal::state()->get('field.storage.deleted'))"

```

If the result is not an empty array, create the missing `field_deleted_data_*` tables:

```
drush php:eval '$deleted_field_storage_configs = \Drupal::state()->get("field.storage.deleted");
$database = \Drupal::database();

foreach($deleted_field_storage_configs as $field_storage_config) {
  $table_name = "field_deleted_data_" . substr(hash("sha256", $field_storage_config->getUniqueStorageIdentifier()), 0, 10);

  $sql_query = "CREATE TABLE IF NOT EXISTS `" . $table_name . "` (
    `bundle` varchar(128) CHARACTER SET ascii NOT NULL DEFAULT '\'\'',
    `deleted` tinyint(4) NOT NULL DEFAULT '\''0'\'',
    `entity_id` int(10) unsigned NOT NULL,
    `revision_id` int(10) unsigned NOT NULL,
    `langcode` varchar(32) CHARACTER SET ascii NOT NULL DEFAULT '\'\'',
    `delta` int(10) unsigned NOT NULL,
    `content_translation_source_value` varchar(12) CHARACTER SET ascii NOT NULL,
    PRIMARY KEY (`entity_id`,`deleted`,`delta`,`langcode`),
    KEY `bundle` (`bundle`),
    KEY `revision_id` (`revision_id`) );";

  $database->query($sql_query);
}
'

```

Remove the fields:

```
vendor/bin/drush php-eval 'field_purge_batch(1000);'

```

Check that no more fields are waiting to be purged:

```
drush php:eval "var_dump(\Drupal::state()->get('field.storage.deleted'))"

```

You can now safely remove `field_deleted_data_*` tables that are still present in the Drupal database.

To perfect this solution:

I based the table name computation on the code of the SqlContentEntityStorage::readFieldItemsToPurge() method.

The better way to do this would be to find a way to get the SqlContentEntityStorage and field storage definition to have the good version of table name computation:

```
$storage_definition = $field_definition->getFieldStorageDefinition();
$table_mapping = $this->getTableMapping();
$table_name = $table_mapping->getDedicatedDataTableName($storage_definition, $storage_definition->isDeleted());

```

---
Tags: 8, entities, database
---


# Question
Title: How can I change the title of the node/add page of a specific content type?
I want to change the title of the node/add page of a specific content type. Twig debug only shows me file names that would also change the titles of other content types. There was a module for this in D7, but unfortunately it was not ported to D8.

# Answer
If you can hide the default page title using CSS, then you could create a custom block for the title and specify to have it show only on the content you want.

In the block configure visibility settings, set the page visibility to be restricted to your content type.

-- But, hiding the default page title block that will only work for you if the admin theme is using the same theme as the front-end site.

I think the admin page title is still passing through that Page title block (the default).. so maybe you can configure that block's visibility to hide on the edit pages where you want your custom block to appear?
> 2 votes

# Answer
Simply use Metatag module. This is the no-code solution.

Use the metatags configuration for the specific content type. And then modyfy the Title field. With the Token module you have more power to modify the title.

Here and here is some documentation about how to use metatgs.
> 1 votes

---
Tags: 8, nodes, forms
---


# Question
Title: "Object of class Drupal\Core\Render\Markup could not be converted to number"
I am receiving an error on a webform I'm developing. Just to give some insight into the webform, the webform is taking in some data (customer type and monthly water consumption) and calculating the cost for Water, Solid Waste, and Sewer. I'm using computed twigs to calculate those cost, and I'm displaying them on the form. (This is where things get complicated). I am displaying current costs and new costs because we'll be applying a new percentage rate. So the user will be able to see current and new costs for Water, Solid Waste, and Sewer. All of this is working.

Now where I'm getting the error is calculating Final Current Cost and Final New Cost. (Basically, the Final Bill, adding Water, Solid Waste, and Sewer to get the Final Bill). I'm using a computed twig for Final Current Bill and Final New Bill.

I am just trying to add

```
{{ data.current_water_bill + data.current_wastewater_bill + data.current_solid_waste_bill }}

```

to get Final Current Bill.

But I'm receiving this error:

> Notice: Object of class Drupal\Core\Render\Markup could not be converted to number in \__TwigTemplate\_b425658712bf48861094edd9faa7ac1869e3493432f58af037adf7477e731085-\>doDisplay() (line 39 of /tmp/rolling/26f07ce/twig/6255afcf3e700\___string\_template\__3115aa\_bPBQWZ4Ws1n7j52GBOzrbmeqE/rL677g5Ips8i5OfG\_zSuLsRcL3s-sFwxT2\_H3MJmsfo.php).

Provide details and any research I've dedicated some time into the error looking for the same error online. I've found a mixture of issues, but ultimately it looks like I need to convert the data into a number. I tried doing so using a twig filter `|number_format` and then I get a new error:

> Notice: Object of class Drupal\Core\Render\Markup could not be converted to float in twig\_number\_format\_filter() (line 611 of /code/vendor/twig/twig/src/Extension/CoreExtension.php).

I can calculate and display the values but I just can't add them. I've added the data into variables and still can't work with them in twig. Any ideas or suggestions would be appreciated.

```
row:
'#type': flexbox
customer_type:
  '#type': select
  '#title': 'Customer Type'
  '#options':
    Industrial: Industrial
    Landscape: Landscape
    Multifamily: Multifamily
    Non-Residential: Non-Residential
    Reclaimed: Reclaimed
    Residential: Residential
  '#required': true
row_3:
'#type': flexbox
'#states':
  visible:
    ':input[name="customer_type"]':
      filled: true
monthly_consumption:
  '#type': number
  '#title': 'Monthly Consumption (in thousands of gallons)'
  '#required': true
  '#max': 100
  '#step': 1
row_6:
'#type': flexbox
'#states':
  visible:
    ':input[name="customer_type"]':
      value: Multifamily
number_of_units:
  '#type': number
  '#title': 'Number of Units'
  '#required': true
row_9:
'#type': flexbox
'#states':
  visible:
    ':input[name="customer_type"]':
      value: Residential
alley_customer:
  '#type': select
  '#title': 'Are you an alley customer? '
  '#options':
    'Yes': 'Yes'
    'No': 'No'
  '#required': true
row_2:
'#type': flexbox
'#states':
  visible:
    ':input[name="customer_type"]':
      filled: true
water_container:
  '#type': fieldset
  '#title': Water
  row_4:
    '#type': flexbox
    current_water_bill:
      '#type': computed_twig
      '#title': 'Current Water Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set monthlyConsumption = data.monthly_consumption %}

            {# If/Else Statement Based on Customer Type #}
            {% if customer == 'Residential' %}
                {# Residential Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Residential houses #}
                {% set firstTenKVol = 1.60 %}
                {% set nextTenKVol = 2.08 %}
                {% set nextFourtyKVol = 2.62 %}
                {% set overSixtyKVol = 3.27 %}

                {# Residential Math Calculation
                ========================= #}
                {% set firstTenK = (monthlyConsumption * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTenK = ((monthlyConsumption - 10) * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextFourtyK = ((monthlyConsumption - 20) * nextFourtyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set overSixtyK = ((monthlyConsumption - 60) * overSixtyKVol) + (40 * nextFourtyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}

                {# If/Else Statement Based on Residential Water Monthly Consumption,
                    Will Display Math Calculations as Current Water Bill
                ========================= #}
                {% if monthlyConsumption >= 61 %}

${{ overSixtyK }}

                {% elseif monthlyConsumption <= 60 and monthlyConsumption >= 21 %}

${{ nextFourtyK }}

                    {% elseif monthlyConsumption <= 20 and monthlyConsumption >= 11 %}

${{ nextTenK }}

                {% elseif monthlyConsumption <= 10 %}

${{ firstTenK }}

                {% endif %}

            {% elseif customer == 'Multifamily' %}
                {# Multifamily Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 29.31 %} {# using 2 inch Meter Size as Default Price for Multifamily houses #}
                {% set firstTenKVol = 0.87 %}
                {% set nextTenKVol = 1.07 %}
                {% set nextTwentyKVol = 1.47 %}
                {% set overFourtyKVol = 2.21 %}

                {# Multifamily Math Calculation
                ========================= #}
                {% set firstTenK = (monthlyConsumption * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTenK = ((monthlyConsumption - 10) * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTwentyK = ((monthlyConsumption - 20) * nextTwentyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set overFourtyK = ((monthlyConsumption - 40) * overFourtyKVol) + (20 * nextTwentyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}

                {# If/Else Statement Based on Multifamily Water Monthly Consumption
                ========================= #}
                {% if monthlyConsumption >= 41 %}

${{ overFourtyK }}

                {% elseif monthlyConsumption <= 40 and monthlyConsumption >= 21 %}

${{ nextTwentyK }}

                    {% elseif monthlyConsumption <= 20 and monthlyConsumption >= 11 %}

${{ nextTenK }}

                {% elseif monthlyConsumption <= 10 %}

${{ firstTenK }}

                {% endif %}

            {% elseif customer == 'Non-Residential' %}
                {# Non-Residential Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Non-Residential #}
                {% set allUsageVol = 2.11 %}

                {# Non-Residential Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage }}

            {% elseif customer == 'Landscape' %}
                {# Landscape Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Landscape #}
                {% set allUsageVol = 2.55 %}

                {# Landscape Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage }}

            {% elseif customer == 'Industrial' %}
                {# Industrial Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Industrial #}
                {% set allUsageVol = 2.08 %}

                {# Industrial Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage }}

            {% elseif customer == 'Reclaimed' %}
                {# Reclaimed Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Reclaimed #}
                {% set allUsageVol = 0.69 %}

                {# Reclaimed Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage }}

            {% endif %}

      '#ajax': true
  row_5:
    '#type': flexbox
    new_water_bill:
      '#type': computed_twig
      '#title': 'New Water Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set monthlyConsumption = data.monthly_consumption %}

            {# If/Else Statement Based on Customer Type #}
            {% if customer == 'Residential' %}
                {# Residential Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Residential houses #}
                {% set firstTenKVol = 1.60 %}
                {% set nextTenKVol = 2.08 %}
                {% set nextFourtyKVol = 2.62 %}
                {% set overSixtyKVol = 3.27 %}
                {% set proposedRateChange = 1.27 %}

                {# Residential Math Calculation
                ========================= #}
                {% set firstTenK = (monthlyConsumption * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTenK = ((monthlyConsumption - 10) * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextFourtyK = ((monthlyConsumption - 20) * nextFourtyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set overSixtyK = ((monthlyConsumption - 60) * overSixtyKVol) + (40 * nextFourtyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}

                {# If/Else Statement Based on Residential Water Monthly Consumption,
                    Will Display Math Calculations as New Water Bill
                ========================= #}
                {% if monthlyConsumption >= 61 %}

${{ overSixtyK + ((overSixtyK * proposedRateChange) /100)|round(2) }}

                {% elseif monthlyConsumption <= 60 and monthlyConsumption >= 21 %}

${{ nextFourtyK + ((nextFourtyK * proposedRateChange) /100)|round(2) }}

                {% elseif monthlyConsumption <= 20 and monthlyConsumption >= 11 %}

${{ nextTenK + ((nextTenK * proposedRateChange) /100)|round(2)  }}

                {% elseif monthlyConsumption <= 10 %}

${{ firstTenK + ((firstTenK * proposedRateChange) /100)|round(2) }}

                {% endif %}

            {% elseif customer == 'Multifamily' %}
                {# Multifamily Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 29.31 %} {# using 2 inch Meter Size as Default Price for Multifamily houses #}
                {% set firstTenKVol = 0.87 %}
                {% set nextTenKVol = 1.07 %}
                {% set nextTwentyKVol = 1.47 %}
                {% set overFourtyKVol = 2.21 %}
                {% set proposedRateChange = 1.83 %}

                {# Multifamily Math Calculation
                ========================= #}
                {% set firstTenK = (monthlyConsumption * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTenK = ((monthlyConsumption - 10) * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set nextTwentyK = ((monthlyConsumption - 20) * nextTwentyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}
                {% set overFourtyK = ((monthlyConsumption - 40) * overFourtyKVol) + (20 * nextTwentyKVol) + (10 * nextTenKVol) + (10 * firstTenKVol) + baseFee|number_format(2) %}

                {# If/Else Statement Based on Multifamily Water Monthly Consumption
                ========================= #}
                {% if monthlyConsumption >= 41 %}

${{ overFourtyK + ((overFourtyK * proposedRateChange) /100)|round(2) }}

                {% elseif monthlyConsumption <= 40 and monthlyConsumption >= 21 %}

${{ nextTwentyK + ((nextTwentyK * proposedRateChange) /100)|round(2) }}

                {% elseif monthlyConsumption <= 20 and monthlyConsumption >= 11 %}

${{ nextTenK + ((nextTenK * proposedRateChange) /100)|round(2)  }}

                {% elseif monthlyConsumption <= 10 %}

${{ firstTenK + ((firstTenK * proposedRateChange) /100)|round(2) }}

                {% endif %}

            {% elseif customer == 'Non-Residential' %}
                {# Non-Residential Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Non-Residential #}
                {% set allUsageVol = 2.11 %}
                {% set proposedRateChange = 3.79 %}

                {# Non-Residential Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage + ((allUsage * proposedRateChange) /100)|round(2) }}

            {% elseif customer == 'Landscape' %}
                {# Landscape Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Landscape #}
                {% set allUsageVol = 2.55 %}
                {% set proposedRateChange = 5.88 %}

                {# Landscape Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage + ((allUsage * proposedRateChange) /100)|round(2) }}

            {% elseif customer == 'Industrial' %}
                {# Industrial Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Industrial #}
                {% set allUsageVol = 2.08 %}
                {% set proposedRateChange = 4.33 %}

                {# Industrial Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage + ((allUsage * proposedRateChange) /100)|round(2) }}

            {% elseif customer == 'Reclaimed' %}
                {# Reclaimed Monthly Water Volume Charges
                ========================= #}
                {% set baseFee = 10.35 %} {# using 3/4 inch Meter Size as Default Price for Reclaimed #}
                {% set allUsageVol = 0.69 %}
                {% set proposedRateChange = 8.00 %}

                {# Reclaimed Math Calculation
                ========================= #}
                {% set allUsage = (monthlyConsumption * allUsageVol) + baseFee|number_format(2) %}

${{ allUsage + ((allUsage * proposedRateChange) /100)|round(2) }}

            {% endif %}

      '#ajax': true
sewer_container:
  '#type': fieldset
  '#title': Sewer
  row_7:
    '#type': flexbox
    current_wastewater_bill:
      '#type': computed_twig
      '#title': 'Current Wastewater Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set monthlyConsumption = data.monthly_consumption %} {# Used only Non-Residential #}

            {# If/Else Statement Based on Customer Type #}
            {% if customer == 'Residential' %}
                {# Residential Wastewater Charges
                ========================= #}
                {% set baseFee = 27.32 %}

                {# Residential Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = baseFee|number_format(2) %}

${{ wasteWaterRate }}

            {% elseif data.customer_type == 'Multifamily' %}
                {# Multifamily Wastewater Charges
                ========================= #}
                {% set baseFee = 9.76 %}
                {% set numberOfUnits = data.number_of_units %}

                {# Multifamily Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = baseFee * numberOfUnits|number_format(2) %}

${{ wasteWaterRate }}

            {% elseif data.customer_type == 'Non-Residential' %}
                {# Non-Residential Wastewater Charges
                ========================= #}
                {% set baseFee = 7.65 %} {# Monthly Base Charge for Non-Residential #}
                {% set volumeFee = 3.49 %} {# Volume Charge Per 1,000 Gallons of Metered Water Use #}

                {# Non-Residential Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = (monthlyConsumption * volumeFee) + baseFee|number_format(2) %}

${{ wasteWaterRate }}

            {% elseif data.customer_type == 'Industrial' %}
                {# Industrial Wastewater Charges
                ========================= #}
                {% set baseFee = 7.65 %} {# Monthly Base Charge for Non-Residential #}
                {% set volumeFee = 3.49 %} {# Volume Charge Per 1,000 Gallons of Metered Water Use #}

                {# Industrial Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = (monthlyConsumption * volumeFee) + baseFee|number_format(2) %}

${{ wasteWaterRate }}

            {% endif %}

      '#ajax': true
  row_8:
    '#type': flexbox
    new_wastewater_bill:
      '#type': computed_twig
      '#title': 'New Wastewater Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set monthlyConsumption = data.monthly_consumption %} {# Used only Non-Residential #}

            {# If/Else Statement Based on Customer Type #}
            {% if customer == 'Residential' %}
                {# Residential Wastewater Charges
                ========================= #}
                {% set baseFee = 27.32 %}
                {% set proposedRateChange = 1.21 %}

                {# Residential Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = baseFee|number_format(2) %}

${{ wasteWaterRate + ((wasteWaterRate * proposedRateChange) /100)|round(2) }}

            {% elseif data.customer_type == 'Multifamily' %}
                {# Multifamily Wastewater Charges
                ========================= #}
                {% set baseFee = 9.76 %}
                {% set numberOfUnits = data.number_of_units %}
                {% set proposedRateChange = 8.30 %}

                {# Multifamily Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = baseFee * numberOfUnits|number_format(2) %}

${{ wasteWaterRate + ((wasteWaterRate * proposedRateChange) /100)|round(2) }}

            {% elseif data.customer_type == 'Non-Residential' %}
                {# Non-Residential Wastewater Charges
                ========================= #}
                {% set baseFee = 7.65 %} {# Monthly Base Charge for Non-Residential #}
                {% set volumeFee = 3.49 %} {# Volume Charge Per 1,000 Gallons of Metered Water Use #}
                {% set proposedRateChange = 6.88 %}

                {# Non-Residential Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = (monthlyConsumption * volumeFee) + baseFee|number_format(2) %}

${{ wasteWaterRate + ((wasteWaterRate * proposedRateChange) /100)|round(2) }}

            {% elseif data.customer_type == 'Industrial' %}
                {# Industrial Wastewater Charges
                ========================= #}
                {% set baseFee = 7.65 %} {# Monthly Base Charge for Non-Residential #}
                {% set volumeFee = 3.49 %} {# Volume Charge Per 1,000 Gallons of Metered Water Use #}
                {% set proposedRateChange = 6.88 %}

                {# Industrial Wastewater Math Calculation
                ========================= #}
                {% set wasteWaterRate = (monthlyConsumption * volumeFee) + baseFee|number_format(2) %}

${{ wasteWaterRate + ((wasteWaterRate * proposedRateChange) /100)|round(2) }}

            {% endif %}

      '#ajax': true
solid_waste_container:
  '#type': fieldset
  '#title': 'Solid Waste'
  '#states':
    visible:
      ':input[name="alley_customer"]':
        filled: true
  row_10:
    '#type': flexbox
    current_solid_waste_bill:
      '#type': computed_twig
      '#title': 'Current Solid Waste Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set hasAlley = data.alley_customer %}

            {# Solid Waste Charges
            ========================= #}
            {% set baseFee = 17.95 %}
            {% set alleyCustomerRate = 1.61 %}

            {# Solid Waste Math Calculation
            ========================= #}
            {% set solidWasteRate = baseFee|number_format(2) %}
            {% set solidWasteRateAlley = baseFee + alleyCustomerRate|number_format(2) %}

            {# Conditional Statement Based on whether customer has alley or not #}
            {% if customer == 'Residential' and hasAlley == 'Yes' %}

${{ solidWasteRateAlley }}

            {% elseif customer == 'Residential' %}

${{ solidWasteRate }}

            {% endif %}

      '#ajax': true
  row_11:
    '#type': flexbox
    new_solid_waste_bill:
      '#type': computed_twig
      '#title': 'New Solid Waste Bill'
      '#template': |

            {# Global Variables
            ================================================== #}
            {% set customer = data.customer_type %}
            {% set hasAlley = data.alley_customer %}

            {# Solid Waste Charges
            ========================= #}
            {% set baseFee = 17.95 %}
            {% set alleyCustomerRate = 1.61 %}
            {% set proposedRateChange = 3.40 %}

            {# Solid Waste Math Calculation
            ========================= #}
            {% set solidWasteRate = baseFee|number_format(2) %}
            {% set solidWasteRateAlley = baseFee + alleyCustomerRate|number_format(2) %}

            {# Conditional Statement Based on whether customer has alley or not #}
            {% if customer == 'Residential' and hasAlley == 'Yes' %}

${{ solidWasteRateAlley + ((solidWasteRateAlley * proposedRateChange) /100)|round(2) }}

            {% elseif customer == 'Residential' %}

${{ solidWasteRate + ((solidWasteRate * proposedRateChange) /100)|round(2) }}

            {% endif %}

      '#ajax': true
row_12:
'#type': flexbox
final_current_bill:
  '#type': computed_twig
  '#title': 'Final Current Bill'
  '#template': '{{ data.current_water_bill + data.current_wastewater_bill + data.current_solid_waste_bill|number_format(2) }}'
  '#ajax': true
final_new_bill:
  '#type': computed_twig
  '#title': 'Final New Bill'
  '#template': '{{ data.new_water_bill + data.new_wastewater_bill + data.new_solid_waste_bill }}'
  '#ajax': true

```

# Answer
> 1 votes
Try passing the values through the `|trim` filter first, to cast them to strings.

---
Tags: webforms
---


# Question
Title: default value for entity reference field
I have a form with an entity reference field and I need to add a default value. I've tried

```
$form['field_op_product']['und'][0]['target_id']['#default_value'] = $product_node->nid;

```

but, that doesn't work. Any idea on how to do this?

The widget type is "AutoComplete"

# Answer
> 7 votes
From the sample code given in question, I assume the `hook_form_alter()` is used. You should first load the referring node, get the Node Title and Node ID from it, and then set the default value using both. This works.

Setting the default value using Node ID alone will not work.

```
$entity_node = node_load($nid);
if ($entity_node) {
    $form['field_op_product'][LANGUAGE_NONE][0]['target_id']['#default_value'] =
        "$entity_node->title ($entity_node->nid)";
}

```

# Answer
> 1 votes
Do you need a default value to be shown the user when the form is first shown?

* If you ment this ... you set the `#default_value` FAPI element using `hook_form_alter()` (or when you build your form) in a custom module to the `$id` of the entity/node you want as the default selected option.

Or if you wanted a default value supplied to the database when the form is submitted (and no answer was ever given)?

* If you meant this, then your code could be placed with your forms `_validate` function to supply a default value if none was given.

**EDIT**: since its "autocomplete" you may need to supply a `#value` as well if you want to change how the form is initially shown. I'm not sure on that.

# Answer
> 0 votes
For drupal 7.54 I found that none of the above worked for single USER entity reference field. My solution needed this code:

```
$form['field_user'][LANGUAGE_NONE]['#default_value'] =
    "$user->name ($user->uid)";

```

This might be due to the fact that only one entity can be set to the field (no multifield) and it is a user field. Here so that someone else needs less debugging than me.

# Answer
> 0 votes
Here's a Drupal 8 way to do this :

```
$client_id = $form_state->getFormObject()->getEntity()->get('field_client_ref')->entity->id();

```

---
Tags: forms, entities
---


# Question
Title: Compress file with ArchiveInterface without file paths
I'm trying to create an archive of log files to be downloadable in a form making a custom module in Drupal 9. In the form, the user can change the format of the archive, as per image:

Here below my code:

```
private function download($form, $form_state) {
  $format = $form_state->getValue('format');
  $folder = $form_state->getValue('folders');

  $date = new DateTime();
  $date = $date->format("y_m_d_H_i_s");

  $logsDirectory = \Drupal::service('file_system')
    ->realpath($folder . "://logs/");
  //Retrieve all the files in the folder.
  $logs = glob($logsDirectory . "/*.log");

  $archiveName = $date . $format;

  $archive_path = \Drupal::service('file_system')
    ->saveData('', 'temporary://' . $archiveName);
  $archive = \Drupal::service('plugin.manager.archiver')
    ->getInstance(['filepath' => $archive_path]);

  foreach ($logs as $log) {
    $archive->add($log);
  }

  $response = new BinaryFileResponse($archive_path);
  $response->headers->set('Content-type', $this->getContentTypes($format));
  $response->headers->set('Content-Disposition', 'attachment;filename="' . $archive_path . '"');
  $form_state->setResponse($response);
}

```

Everything is going fine, I managed to achieve a button in this way that, when pressed, downloads the archive with all the log files inside. The problem is that inside of this zip all the files are inside their absolute path, in this way:

This is because in the ArchiveInterface Class the **add** method only accepts one parameter, `$file_path`, and it is not supported to add a second parameter to specify the name of the files. How could I solve this problem, being able of adding inside the archive only the files and not all the subfolders?

# Answer
Drupal's Zip archiver doesn't support that functionality directly, but the underlying PHP `ZipArchive` it uses does (see `ZipArchive::addFile()`), and you can get a reference to that object from the Drupal archiver.

For example:

```
$zip_archive = $archive->getArchive();
foreach ($logs as $log) {
  $zip_archive->addFile($log, basename($log));
}

```

Bear in mind that this only works well for a `glob` that brings back unique file names every time. If the structure changes and you end up with subfolders containing files with name clashes, you'll need to update the loop to accommodate, or risk some files not being included.
> 0 votes

---
Tags: forms, files, 9
---


# Question
Title: How do I skip calling a custom validation function in a form with AJAX dropdowns?
I am using headless Drupal with .NET middleware. I have a Drupal 9 form. This form contains two drop-down elements which are filled up depending on a value selected in a third drop-down. I have a custom validation handler just after those AJAX drop-down elements, where I store some data in a .NET database.

This is my code for `hook_form_alter()`.

```
$form['technology_type'] = [
  '#type' => 'select',
  '#title' => t('Technology Type'),
  '#options' => $tech_type_options,
  '#default_value' => $t_selected_option,
  '#ajax' => [
    'callback' => 'techlistDropdownCallback',
    'wrapper' => 'techlist-fieldset-container',
    'event' => 'change',
  ],
];

if ($t_selected_option != '') {
  $tech_options = array(0 => '- None -');
  $tech_options = custom_authorization_tech_options($t_selected_option);
}
else {
  $tech_options = array(0 => '- None -');
}

$form['techlist-select-fieldset-container']= [
  '#type' => 'container',
  '#attributes' => ['id' => 'techlist-fieldset-container'],
];

$form['techlist-select-fieldset-container']['source_tech'] = [
  '#type' => 'select',
  '#title' => t('Source Tech'),
  '#options' => $tech_options,
  '#default_value' => !empty($source_tech_value) ? $source_tech_value : $form_state->getValue('source_tech'),
  '#multiple' => true,
];

$form['techlist-select-fieldset-container']['target_tech'] = [
  '#type' => 'select',
  '#title' => t('Target Tech'),
  '#options' => $tech_options,
  '#default_value' => !empty($target_tech_value) ? $target_tech_value : $form_state->getValue('target_tech'),
  '#multiple' => true,
];

if ($t_selected_option == 0) {
  $form['techlist-select-fieldset-container']['source_tech']['#title'] = t('Source Tech (You must choose tech type first)');
  $form['techlist-select-fieldset-container']['source_tech']['#disabled'] = TRUE;
  $form['techlist-select-fieldset-container']['target_tech']['#title'] = t('Target Tech (You must choose tech type first)');
  $form['techlist-select-fieldset-container']['target_tech']['#disabled'] = TRUE;
}

array_unshift($form['#validate'],'custom_authorization_mak_form_validate');

```

Whenever these dependent drop-downs get filled up with values, the validation function gets called somehow and incomplete data gets automatically stored in database even without pressing the save button of the form.

How do I avoid this weird issue?

I just want to fill up the drop-down elements using AJAX, then call the validation handler to store data in database.

# Answer
To prevent the form submission when the form is submitted with AJAX (when you change the state of the form with AJAX), in the validation handler use $form\_state-\>setRebuild();
> 0 votes

---
Tags: forms, ajax, 9
---


# Question
Title: How to permit users to view unpublished nodes which they didn't create?
I have created two roles: Editor and Reviewer.

Editor must only create unpublished nodes; instead, Reviewer must publish and view these nodes.

How can I make users with a role see unpublished nodes? If I set the permission "*Access the content overview page*", the users with that role can modify all contents and I don't want this.

I tried the View unpublished module, but it has an issue, as reported in View unpublished breaks access rules defined by Views.

How to permit users to view unpublished nodes which they didn't create?

# Answer
# Solution 1

I would "*set the permissions 'Access the content overview page'* ...", and combine that with using the Rules module to prevent "*the Reviewer can modify all contents*". Read on for more details about how to do so.

Create a rule (using the Rules module), that is a variation of the rule I included (in export format) in my answer to the question about "How to restrict access to a node via node/12 and allow access via a path like content/sometitle?".

These are the changes to that rule to make it work for this case also:

* Append `/edit` at the end anywhere there is already something like `node/%` (I assume when somebody tries to edit a node, they use a node with `/edit` at the end, though any variation of that should work in a similar way).
* Add a Rules '*Condition*' to verify that the current user trying to do such edit does NOT have role "Editor".
* You probably also need to add another Rules condition like "content is of type" (i.e. 'article' in your case, something that is not mentioned in your original question, but in an extra comment). That way the rules action does NOT apply for ay other content type.
* Change the "Message" (in the Rules '*Action*') to something that fits your needs.
* Modify the Rules '*Action*' to fit your own requirements, e.g. to issue a redirect to some other page.

Note that the Rules *Event* is "Drupal Is Initializing" ... Otherwise you are, for sure, "too late": you don't want the rule to be triggered after the edit session has been started already, instead it should be triggered before that. I.e when Drupal is getting ready to start an edit session.

Haven't experimented/tried creating this rule (= variation of the rule in the answer I mentioned above). But pretty sure it'll work.

You may also want to look at my answer to "https://drupal.stackexchange.com/questions/182958/how-to-limit-appearance-settings-based-on-roles-permissions/182959#182959" for another example of a rule, which uses some techniques similar to what you'd need here.

# Solution 2

*Solution 1* should work, but its weakness is that it's based on "Bypass Content Access Control". Personally I do not like that either. So I agree with your comment about that (a comment which has been removed via moderation). But hey, it's "a" solution to answer "your" (original) question.

If it was up to me to implement a "real" solution for the challenge you're trying to solve, I'd go for a plan b, as further detailed below.

Have a look at my answers to either of these questions:

These answers explain how you can implement a workflow that is pretty (though not exactly) similar to what you are looking for.

To do so, it "only" requires you to use these modules (and regular content types):

And by using such approach, it does not require modules like "Webform" or "Workbench" (modules that are typically involved for these kinds of workfows).

If you're not familiar with Rules, checkout the video tutorials Learn the Rules framework. And/or the similar set of 8 video tutorials about the Flag module.

**Note**: This "Solution 2" is also how I implemented a variation of your question on 1 of our own sites: it starts from an **Issue** (= problem or feature request), evolves to a **Recipe** (= instructions about how to get something to work) and ends with a **Software solution** (= a plugin or so, whereas the Recipe becomes part of the documentation). Node Convert and Content Access do most of the work for this, and even works in D6 ...
> 3 votes

# Answer
### Content Access

> This module allows you to manage permissions for content types by role and author. It allows you to specifiy custom view, edit and delete permissions **for each content type**. Optionally you can enable per content access settings, so you can customize the access for each content node.
> 2 votes

# Answer
You can use unpublished\_node\_permissions which creates granular permissions for each role which can be edited by an admin under `admin/people/permissions` to view unpublished nodes per content type.

It also takes care views permissions so for example `admin/content` view will filter nodes correctly as per the user's role permissions.

NOTE: there is a known bug with D8 multilingual sites and views that might create undersireable results.
> 1 votes

# Answer
You can use https://www.drupal.org/project/access\_unpublished. You do not need to worry about the role or even creating user. This module generate a hash key as query parameter along with node URL. You can also set lifetime of the hash key before it expires. You just need to pass this to the person whom you want to give access to. This is very useful in case of proofreaders.

Hope this is helpful for others too.
> 0 votes

---
Tags: nodes, users
---


# Question
Title: programmatically get child nodes referencing parent by entity reference uuid, using loadByProperties & entityTypeManager or other way without views
I tried this answer:

https://drupal.stackexchange.com/a/298084/1082

But I can't seem to use

`'field_scientists' => $entity_reference_uuid`

where, in my case, `field_scientists` is a field of type Entity Reference UUID - which is a field type provided by https://www.drupal.org/project/entity\_reference\_uuid module

What happens for me is that I get nothing back, my results array from that example is empty.

Looking to do this programmatically in my own custom module, rather than use a Drupal View.

If there's another way e.g. that uses the `->query` method for querying the database I'd be happy to use that programmatic approach.

Thank you.

**Update**

An example of a `uuid` of a `node` in my case is `BMSSYS0000051988`.

This was set in a migration import from a field in a CSV.

My attempts are:

**1. based on the example in the other question:** https://drupal.stackexchange.com/a/298084/1082

```
  $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties([
    'type' => 'bol',
    'field_parent_uuid' => $taxonkey,
  ]);

```

**2. db query**

```
$query = \Drupal::entityQuery('node')
->condition('status', NODE_PUBLISHED)
->condition('type', 'bol');
$and = $query->andConditionGroup();
$and->condition('field_parent_uuid',  $taxonkey);
$query->condition($and);
$result = $query->execute();

```

where `$taxonkey` is `BMSSYS0000051988`

both 1 and 2 attempts above return an empty array.

**Update 2**

here is my migration config that shows uuid being written to from a field in the csv. Is this legal? Should a developer's code change the uuid value or should uuid only be handled by Drupal core?

```
dependencies: {  }
id: bol_csv_import
class: null
field_plugin_method: null
cck_plugin_method: null
migration_tags: null
migration_group: defaultl: publicbins
label: 'Import bol species data'
source:
  plugin: csv
  path: ./data/taxonomy_species_with_unpacked_bold.csv
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  ids:
    - uuid
  fields:
    -
      name: uuidl: publicbins
      label: 'NBN id'
    -
      name: parent_uuid
      label: 'NBN id of parent'
    -
      name: name
      label: Name
    -
      name: rank
      label: 'Taxonomic Rank'
    -
      name: taxon_key
      label: 'Taxon Key'
    -
      name: authority
      label: authority
    -
      name: specimenrecords
      label: specimenrecords
    -
      name: publicrecords
      label: publicrecords
    -
      name: publicbins
      label: publicbins
    -
      name: taxid
      label: 'NBN Taxon ID'
process:
  title: name
  uid:
    plugin: default_value
    default_value: 1
  uuid: uuid
  field_parent_uuid: parent_uuid
  field_taxon_key: taxon_key
  field_authority: authority
  field_rank: rank
  field_num_bold_barcode_specimens: specimenrecords
  field_num_bold_public_records: publicrecords
  field_num_bold_public_bins: publicbins
  field_bold_taxon_id: taxid
  type:
    plugin: default_value
    default_value: bol
destination:
  plugin: 'entity:node'
migration_dependencies: null

```

**Update 3**

I'll write a db query to solve this issue. Running a command line sql indicates this approach could work:

```
MariaDB [db]> select * from node where nid = 246;
+-----+------+------+------------------+----------+
| nid | vid  | type | uuid             | langcode |
+-----+------+------+------------------+----------+
| 246 |  248 | bol  | NBNORG0000041189 | en       |
+-----+------+------+------------------+----------+
1 row in set (0.001 sec)

```

# Answer
In theory this should work, the field type sets the UUID as main property: EntityReferenceUuidItem:: mainPropertyName()

It might be that Drupal is confused and handling the field as a standard entity reference field because it extends the core field type.

To make clear which field property you are querying append it with a dot:

```
'field_scientists.target_uuid' => $entity_reference_uuid

```

Which should work for both, loadByProperties or an entity query:

```
->condition('field_scientists.target_uuid', $entity_reference_uuid)

```

The first is only a shortcut for the second using the same query engine.
> 0 votes

---
Tags: entities, 9
---


# Question
Title: How can I add a direct link to the edit account settings page in a menu?
Ok, I must be missing something obvious, but I'm having trouble adding a link to `user/%/edit` to the main menu. In the Menu UI, I clicked "add link," set the title to "Account settings," and then was at a loss about what to put for the path. I know how to generate a link to the account edit page using views, which is what I've always done before, but this time I actually need to add the link to the "Main Menu."

# Answer
In **Drupal 8,9,10 etc.** you can do this by providing a custom route to point to `/user/edit` for example and have this route call a controller to perform a simple redirect. You can then simply link to `/user/edit` from anywhere you want and the redirect will bring the user to their correct `/user/%/edit` form.

The User Current Paths module does exactly that. Use this module or have a look a their approach, which can be extended easily to provide more complex dynamic redirects as well.
> 0 votes

# Answer
Try this module menu\_token , it allows to use tokens in menu

> Menu Token module provides tokens, that could be used in title or in path of menu items (links). For example, if you create a menu item with path: "user/\[current-user:uid\]", the url will be changed "on fly" to: "user/1" (assuming you are user 1).
> 11 votes

# Answer
You can't use % as a wildcard when adding a menu item like that.

The me aliases module can help you do it.

You install that module and then you can add a menu item to user/me/edit and it will go to the currently logged in user's edit page.
> 5 votes

# Answer
Create a node with input format filter set as **PHP code** and copy/paste the following code:

```
<?php
drupal_goto('user/'.$GLOBALS['user']->uid.'/edit');
?>

```

Under menu settings, create a menu link and add it to a menu.

https://drupal.org/comment/4098302#comment-4098302
> 0 votes

---
Tags: routes
---


# Question
Title: Webform Multistep - conditional wizard skipping
Is there a way to create a multistep form in Webform and add conditional logic somehow that, based on submission values, certain steps are skipped?

Example, I have a 10 step wizard Webform. Based on certain answers in the first 3 steps, steps 4-6 may be skipped, or in some cases, sent from step 3 to the final step. In other cases, the user would go through every single step (normal).

I tried looking around for examples but didn't come across anything concrete. I did find this, but I am not sure if that is still current?

Webform version: 6.x

# Answer
> 1 votes
Wizard pages support conditional logic which can be used to skip steps as needed.

# Answer
> -2 votes
I'm getting frustrated because I have the same problem - conditional logic controlling a wizard page doesn't work. I see this question over and over online but respondents just keep saying it works, but nobody explains what we are all doing wrong.

Presumably if so many people get stuck on this, there is something counter-intuitive about how we should be setting it up. Please help!

---
Tags: 8, webforms
---


title: Get raw and relative path of a file uri

text:
# Question
Title: Get raw and relative path of a file uri
I have a file with an uri and I want to get its raw and relative path.

Uri: `public://videos/Test Video.mp4` Path: `/sites/default/files/videos/Test Video.mp4`

I found already a way to do this:

```
$file_uri = $file->getFileUri();
// public://videos/Test Video.mp4

$absolute_url = file_create_url($file_uri);
// https://www.example.com/sites/default/files/videos/Test%20Video.mp4

$relative_url = file_url_transform_relative($absolute_url);
// /sites/default/files/videos/Test%20Video.mp4

$relative_raw_url = rawurldecode($relative_url);
// /sites/default/files/videos/Test Video.mp4

```

Is this the Drupal-way? Or is there a better solution for doing this?

# Answer
> 10 votes
I had to do this recently and found this solution using Drupal 9.1.

```
$file = File::load($fid);

$relative_file_url = $file->createFileUrl(TRUE);
$absolute_file_url = $file->createFileUrl(FALSE);

```

I found the createFileUrl() function in web/core/modules/file/src/Entity/File.php. Maybe this would be considered "the way?"

# Answer
> 3 votes
The "Drupal way" is always a fuzzy term because there's usually more than one answer that works.

Anyway, if you're looking for something less verbose, it would help to look at the `File` object and it's `url()` method. That saves you some steps and might save you some work down the road if the old D7 file module API functions get slated for depreciation (like `file_load` has).

Lastly, it always helps to use native PHP functions when you can since they make things more portable. To wit, `parse_url()` allows you to slice/dice URLs to the components you want.

Putting it all together, `rawurldecode(parse_url($file->url(), PHP_URL_PATH))` pulls all your function call together for one result.

# Answer
> 2 votes
```
$relative_file_url =  \Drupal::service('file_url_generator')
    ->generateAbsoluteString($uri);

```

---
Tags: 8, files, uri
---


# Question
Title: Checkout Flow Submit Pane Form Checkbox to Boolean Field
I create a Checkbox in the Checkout Flow, CheckoutPane. How i can send the Value of the Checkbox to a Entity in the User-Profile or the Order.

Description: I need a Checkbox in the CheckoutPane, when the Customer select the Checkbox and click submit i must save the value in a Field in the Order or Profile of the specific user with the date. When the customer select the checkbox first time, its hidden for future orders.

The checkbox is correctly printed, but cannot submit the value of the checkbox to a entity in order, or better a entity in the user-profile. I create the Field field\_customer\_check in the Order and try it same as in the Drupal Commerce Checkout Flow Example with comments. https://docs.drupalcommerce.org/commerce2/developer-guide/checkout/create-custom-checkout-pane

```
public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
  $values = $form_state->getValue($pane_form['#parents']);
  $this->order->setData('order_comment', $values['comment']);
}

```

Here is my previous Code for the CheckoutPane:

```
<?php

namespace Drupal\mymodule_checkout\Plugin\Commerce\CheckoutPane;

use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneBase;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutPane\CheckoutPaneInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce\InlineFormManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowInterface;

/**
 * Provides the completion message pane.
 *
 * @CommerceCheckoutPane(
 *   id = "agree_terms",
 *   label = @Translation("Permanent agree"),
 * )
 */
class AgreeTerms extends CheckoutPaneBase implements CheckoutPaneInterface {
public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $order_id = $this->order->id();

        $pane_form['user_check_accept'] = [
          '#type' => 'checkbox',
          '#default_value' => FALSE,
          '#title' =>$this->t('My Checkbox Title'),
          '#required' => FALSE,
          '#weight' => $this->getWeight(),
        ];

        return $pane_form;

  }
public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
  $values = $form_state->getValue($pane_form['#parents']);

  // How to submit the value from a Checkbox in a Boolean Field in the Order
  // Problem, field_customer_check not get any data
  $this->order->setData('field_customer_check', $values['user_check_accept']);

}

 }

```

# Answer
> 1 votes
If I got the question right, you have 2 different use cases; first, you want to update the user field with values from the pane, and the second is to hide it if the user already filled the information in a previous purchase.

To solve the first problem, you can update the user fields by calling the current user and setting the value that you want as the following:

```
public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
  $values = $form_state->getValue($pane_form['#parents']);

  // Get the current user entity.
  $user = User::load(\Drupal::currentUser());

  // Set the value of the field.
  $user->FIELD_NAME->value = $form_state->getValue('THE VALUE');

  // Save the user entity.
  $user->save;

}

```

For the second part of the question, you need to check for the values while building the form and you can get the current user in the same way using

```
$user = User::load(\Drupal::currentUser()->id());

```

and to check for the existing value in the same way:

```
if (!empty($user->FIELD_NAME->value)) { DO SOMETHING }

```

# Answer
> 0 votes
I try now many times to save it in the user field\_revoke\_consent, but i not bring the value from the checkbox into this field.

```
  public function submitPaneForm(array &$pane_form, FormStateInterface $form_state, array &$complete_form) {
    $values = $form_state->getValue($pane_form['#parents']);

    // Get the current user entity.
    $user = User::load(\Drupal::currentUser()->id());
    $fieldconsent = ('field_revoke_consent');
     // Set the value of the field.
     $user->$fieldconsent->value = $form_state->getValue($pane_form['user_consent_accept']);

      // Save the user entity.
    $user->save;

    /*
    $pane = $form_state->getValue('agree_terms');

    $values = $form_state->getValue($pane_form['#parents']);

    $checked = $form_state->getValue($pane_form['user_consent_accept']['#default_value']);

    $user = User::load(\Drupal::currentUser()->id());

   if($checked ==['#default_value' => 1] ) {$user->field_revoke_consent->value = 1; }

   $user->field_revoke_consent->value = $form_state->getValue($pane_form['user_consent_accept']);
  $user->save;
   */
  }
}

```

---
Tags: 8, entities, forms, commerce
---


# Question
Title: Generating an absolute node URL from its node id
I think the question is self explanatory. I got a node ID and I need to create its absolute URL somehow. I can do this but (I think) this won't work every where in the site:

```
<a href="?q=node/node-id">Node Title</a>

```

Please correct me if I am wrong.

Is there a function that I can give the node id and returns me back the absolute path of it?

# Answer
Yes, the `url()` function:

```
$url = url("node/$nid");

```
> 8 votes

# Answer
# Drupal 8

```
$nid = 5;
// Or $nid = $node->id();
$node_title = 'Node Title'
// Or $node->getTitle();

```

Create absolute URL:

```
// Will output http://example.com/path-to-my-node
$options = ['absolute' => TRUE];
$url_object = \Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => $nid], $options);
// In Twig use {{ url_object }}.
// In PHP (outside a render array) use $url_object->toString().

```

Create absolute link object (and inner span):

```
// Will output <a href="http://example.com/path-to-my-node" class="this-class"><span>Node Title</span></a>
$options = ['absolute' => TRUE, 'attributes' => ['class' => 'this-class']];
$node_title = \Drupal\Core\Render\Markup::create('<span>' . $node_title . '</span>');
$link_object = \Drupal\Core\Link::createFromRoute($node_title, 'entity.node.canonical', ['node' => $nid], $options);
// In Twig use {{ link_object }}.
// In PHP (outside a render array) use $link_object->toString().

```
> 16 votes

# Answer
In **Drupal 8** you can use toLink function if you already load the node to generate an absolute link.

```
$event = \Drupal::entityTypeManager()->getStorage('node')->load($event_id);
if (!$event)
  return false;

// add ->toString() or other if needed
$abs_link = $event->toLink(NULL, 'canonical', ['absolute' => true]);

```

For example.

This solution use same principle that previous answers but its seems to me more practical if you need other info from this node or if the node is already loaded.
> 4 votes

# Answer
Yes, the `l()` function:

```
$link = l("Node Title", $nid);
print $link;

```

Above code, prints the following output:

> `<a href="/node/XXX">Node Title</a>`

If you want to get **absolute URL** as you stated in your question:

```
$link = l('Node Title', $nid, array('absolute' => TRUE));

```

which will generate the link like:

> `<a href="http://example.com/node/XXX">Node Title</a>`
> 3 votes

# Answer
# Drupal 7

You can get path alias using drupal\_get\_path\_alias()

it will return:

> An aliased path if one was found, or the original path if no alias was found.

This function will give you pretty path if it is created by admin or by `pathauto` module. After that you can use path alias to build absolute url.

There are many ways to do that, you can use url() or l() or you can even use dirtier approach and concatenate `global $base_url` to path alias which will give you just absolute url as a string and print it in whatever template you want.

using `drupal_get_path_alias`:

```
$path_alias = drupal_get_path_alias("node/{node_id}", $language_code);

```

# Drupal 8

There are not above functions in Drupal 8 but you can do same using `path.alias` service.

e.g.

```
$path_alias = \Drupal::service('path.alias_manager')->getAliasByPath($system_path, $langcode);

```

# More

Please check this link for more information on both versions
> 1 votes

# Answer
## Drupal 9

```
$entity->toUrl('canonical', ['absolute' => TRUE])->toString();

```
> 0 votes

# Answer
# Drupal 9

Best practice is the AliasManager service: path\_alias.manager

```
$alias = \Drupal::service('path_alias.manager')->getAliasByPath('/node/' . $nid);

```
> -3 votes

---
Tags: nodes
---


title: Send mail with Data Selector

text:
# Question
Title: Send mail with Data Selector
In Drupal 9 Rules 8.x alpha 7 - I have a rule working. However, I am trying to send an email to the user of the account that is changed.

I am trying to figure out the **data selector** to make this happen. I have tried token for an email: `{{ profile.uid.entity.mail }}` I have tried `profile.uid.entity.mail.value` as a data selector and many other things I am finding online.

I have Entity is of Bundle and Field is of type in the conditions to grab the field in the user account.

If I put in a specific email it works. Anyone figure out the data selector for this?

# Answer
> 0 votes
Okay, it took a while but I got it to work. I am using the Profile module with the Drupal account. This rule is on Profile update.

In the Condition: you need 'Entity is of Type' - data\_selector = profile, and value = profile Then you need 'Entity has field' with data\_selection = `@user.current_user_context:current_user` and value as 'mail'

Than...You create an Action "send Mail' - in the Send to: direct input I used this `{{ profile.uid.entity.mail }}` Added a message and tested.

It works!!!

Hope that helps someone.

---
Tags: rules, 9
---


# Question
Title: How can I add cache context to custom menu link?
I have two routes that receive user as route parameter, and i need a menu link for every one in account menu. So I added in my \*links.menu.yml

```
client_account_links:
  deriver: \Drupal\my_module\Plugin\Menu\CustomLinks\ClientMenuLinksDerivative
  class: \Drupal\my_module\Plugin\Menu\CustomMenuLink

```

And I created my CustomMenuLink class in my\_module/src/Plugin/Menu with

```
<?php

namespace Drupal\my_module\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;

/**
* A menu link that cache by user context.
*/
class CustomMenuLink extends MenuLinkDefault {

    public function getCacheMaxAge() {
        return 0;
    }

    public function getCacheContexts() {
        return ['user'];
    }
}

```

And my ClientMenuLinksDerivative has:

```
<?php

namespace Drupal\my_module\Plugin\Menu\CustomLinks;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxy;
use Drupal\user\Entity\User;
use Drupal\personas\PersonaUtility;

class ClientMenuLinksDerivative extends DeriverBase implements ContainerDeriverInterface {

    protected $account;

    protected $uid;

    public function __construct(AccountProxy $current_user) {
        $this->uid = $current_user->id();
        $this->account = User::load($current_user->id());
    }

    public static function create(ContainerInterface $container, $base_plugin_id) {
        return new static(
            $container->get('current_user')
        );
    }

    public function getDerivativeDefinitions($base_plugin_definition) {
        $links = array();
        if (PersonaUtility::hasPersona($this->account, 'cliente_konsey')) {
           $links['contratos_cliente'] = [
                'title' => 'Contratos',
                'description' => 'Mis Contratos',
                'menu_name' => 'account',
                'weight' => 3,
                'route_name' => 'page_manager.page_view_mis_contratos_mis_contratos-panels_variant-0',
                'route_parameters' => ['user' => $this->uid]
            ] + $base_plugin_definition;

        $links['solicitudes_cliente'] = [
                'title' => 'Solicitudes',
                'description' => 'Mis solicitudes',
                'menu_name' => 'account',
                'weight' => 4,
                'route_name' => 'page_manager.page_view_mis_solicitudes_mis_solicitudes-panels_variant-0',
                'route_parameters' => ['user' => $this->uid]
            ] + $base_plugin_definition;
    }

    return $links;
}

```

}

This create my menu links in the account menu but the route parameter always is the same, so if I change user, the links send me to another user page, the user that run the code before that cached.

My question is how I can create custom menu links, with route parameters (user in my case), and the links change by user? because this don't work. Also I tried with hook\_menu\_links\_discovered\_alter(), but without lucky.

# Answer
> 7 votes
The deriver class is to provide multiple derivatives of one plugin class. In your case you can probably do this without deriver in a OOP way or configure the static details of the menu link in the yaml file, because you only need two variants.

But these are only different ways to achieve the same goal and is not the main problem here.

I think this is the code that depends on the current user. The deriver class is not the right place for this. You should be able to implement this in the custom menu link class. For example provide a dynamic route parameter in getRouteParameters():

```
public function getRouteParameters() {
  return ['user' => $this->uid];
}

```

Then the cache context you have already defined should work:

```
public function getCacheContexts() {
    return ['user'];
}

```

# Answer
> 6 votes
As @4k4 says you don't need the derivates class in this case you need to do something like this example:

**.links.menu.yml file:**

```
client_account_links:
  class: Drupal\my_module\Plugin\Menu\UserProfile
  menu_name: account
  title: 'Edit Your Profile'
  route_name:  entity.user.edit_form

```

**The class:**

```
<?php

namespace Drupal\my_module\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;
use Drupal\Core\Menu\StaticMenuLinkOverridesInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Session\AccountInterface;

/**
 * Represents a menu link for a user profile edition.
 */
class UserProfile extends MenuLinkDefault {

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, StaticMenuLinkOverridesInterface $static_override, AccountInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $static_override);

    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('menu_link.static.overrides'),
      $container->get('current_user'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    return ['user'];
  }

  /**
   * {@inheritdoc}
   */
  public function getRouteParameters() {
    // If the user is not Anonymous.
    if (!$this->currentUser->isAnonymous()) {
      // Getting the uid.
      $uid = $this->currentUser->id();
      // Adding the link.
      return ['user' => $uid];
    }
    return [];
  }

}

```

# Answer
> 0 votes
You can add a cache context to a menu link in a `hook_menu_preprocess`, but because of this issue the contexts won't bubble to the menu, so you'll have to also add them to the menu render array.

---
Tags: 8, routes, caching, navigation
---


# Question
Title: Is possible to find the "original" route while executing code from a widget?
I'm on D9.

I've a node edit form with a *media* field using the *media library* widget.

When a new media is added I'd need to run some custom code to replace one token, of the media path location, depending on the value of the node itself.

However, the route available with `\Drupal::routeMatch()` is `media_library.ui` and there is no *node object* available

I suppose this is correct, as the code is execute during the request "inside the media library widget".

Thus, i'm trying to find if is possibile somehow to get the "main\original" request from in that moment and the relative *node object* or if it is impossible. In the latter case, do you have idea if that objective is somehow possible?

# Answer
To alter a widget form, Drupal invokes these hooks.

In both the cases, you can get the node to which the field using the *Media library* widget is attached using with code similar to the following one.

```
if ($context['widget']->getPluginId() == 'media_library_widget') {
  $field_definition = $context['items']->getFieldDefinition();
  if ($field_definition->getTargetEntityTypeId() == 'node') {
    $node = $context['items']->getEntity();
    // Use $node.
  }
}

```

If you are instead trying to alter the value of a token when it's used for that widget, that isn't possible, since the hook to alter the tokens (`hook_tokens_alter()`) only knows for which entity type the token is requested (`$context['type']`) and for which entity object (`$context['data'][$context['type']]`).
> 2 votes

# Answer
Here is my code which does a similar job - extracting the node from the entity browser parameters (However I am not sure which media path location are you going to change).

```
/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function my_module_form_entity_browser_media_entity_browser_modal_form_alter(&$form, FormStateInterface $form_state) {
  // @todo Move that code to ClassResolver.
  /** @var \Drupal\entity_browser\Form\EntityBrowserForm $form_object */
  $form_object = $form_state->getFormObject();
  $eb = $form_object->getEntityBrowser();
  $eb_params = $eb->getAdditionalWidgetParameters();
  if (!isset($eb_params["path_parts"][1]) || !isset($eb_params["path_parts"][2])) {
    return;
  }

  if (!is_numeric($eb_params["path_parts"][2])) {
    return;
  }

  $params = [];
  try {
    $params = Url::fromUserInput(implode('/', $eb_params["path_parts"]))->getRouteParameters();
  }
  catch (Exception $exception) {
    Drupal::messenger()->addError($exception->getMessage());
  }

  $node = NULL;
  if (isset($params['node'])) {
    $node = Node::load($params['node']);
  }

  $group = NULL;
  if (isset($params['group'])) {
    $group = Group::load($params['group']);
  }

  if (empty($node) && empty($group)) {
    return;
  }

  $labels = [];
  $group_links = [];
  $group_urls = [];
  $gids = [];
  $gid = NULL;
  $form['#attributes']['data-parent_node'] = NULL;

  switch (!$node ? 'group' : 'node') {
    case 'group':
      $gid = $group->id();
      break;
    case 'node':
      $group_contents = GroupContent::loadByEntity($node);
      foreach ($group_contents as $group_content) {
        $group = $group_content->getGroup();
        $gids[] = $group->id();
        $labels[] = $group->label();
        $group_urls[] = $group->toUrl()->toString();
        $group_links[] = $group->toLink($group->label())->toString();
      }

      $form['#attributes']['data-parent_node'] = $node->id();

      $gid = reset($gids);
      break;
  }

  $form['#attributes']['data-parent_group_names'] = json_encode($labels);
  $form['#attributes']['data-parent_group_urls'] = json_encode($group_urls);
  $form['#attributes']['data-parent_group_links'] = json_encode($group_links);
  $form['#attributes']['data-parent_group_ids'] = json_encode($gids);
  $form['#attributes']['data-parent_group_id'] = $gid;
}

```
> 0 votes

---
Tags: entities, 9
---


# Question
Title: Pass arguments to the entity_browser iframe url (modal)
I have a form I have a field of type Date Range, I also have another field of type entity\_browser(modal) with a selection view widget.

The normal behavior when I click the Button of the entity browser field, is the opening of the modal, if we inspect the code it can be seen similar to this:

```
<form
   data-entity-browser-uuid="a9b7680318c9f1a1aca1abc308d8c6d0ac880b4a"
   data-drupal-selector="entity-browser-event-browser-form"
   action="/entity-browser/modal/event_browser?uuid=a9b7680318c9f1a1aca1abc308d8c6d0ac880b4a&original_path=/node/add/activity"
   method="post"
   id="entity-browser-event-browser-form">....
</form>

```

What I'm trying to do, is that as the dates are selected, pass these values as arguments to the iframe url something like this:

```
<form
   action="/entity-browser/modal/event_browser?uuid=a9b7680318c9f1a1aca1abc308d8c6d0ac880b4&aoriginal_path=/node/add/activity&start=12-02-2022&end=14-02-2022"
....
</form>

```

Then from the view take these values and filter the contents.

**What i have so far**

Reviewing the code of the entity\_browser module, I see that the Modal class (`Drupal\entity_browser\Plugin\EntityBrowser\Display\Modal`), as part of the process hook, this dispatch an event to which one can subscribe.

In fact, i can add parameters to the query argument in this subscription, i have harcoded the values as a test, but they do not render when I refresh the form where I create the content that contains the entity\_browser type field.

Example:

```
public function onAlterEntityBrowserDisplayData(AlterEntityBrowserDisplayData $event) {
    if ($event->getBrowserID() === "event_browser") {
       $data = $event->getData();
     if (isset($data["query_parameters"]["query"])) {
        $data["query_parameters"]["query"]['start'] = '12-02-2022';
        $data["query_parameters"]["query"]['end'] = '14-02-2022';
        $event->setData($data);
      }
    }

  }

```

If I could get this to work, then I'd have to figure out some way with ajax to keep changing these values as the values in the date field change.

I don't know if this is the best way to do it, I don't know what you think.

**Update**

The subscription to the event is working, that is, when rendering the content form, the new parameters are added to the iframe url.

The only thing that I would be missing is the update of the parameters via ajax when the values of the date field change.

I can add an ajax callback to the date field that listen when the value changes, I see there is an input field of type hidden where it seems to have the values that entity\_browser will use. The problem is that it doesn't have an id to replace the values with.

Example:

```
<input
   data-drupal-selector="edit-field-event-entity-browser-entity-browser-path"
   type="hidden"
   name="field_evento[entity_browser][entity_browser][path]"
   value="/entity-browser/modal/event_browser?uuid=1d0cbf414d0af02542405648750ccf4d157438fb&original_path=/node/add/activity&start=12-02-2022&end=14-02-2022"
>

```

The problem is that it doesn't have an id to replace the values with.

What can be done in these cases?

# Answer
> 0 votes
1. I would suggest creating a custom Entity Reference widget, that extends the one that you are trying to alter.
2. Then use Drupal form states to make your entity reference field conditional, and display it only if the date range is selected.
3. Add JS code that updates the values submitted (add the selected dates) when the entity browser open button is pressed.
4. in `hook_form_entity_browser_media_entity_browser_modal_form_alter` or `hook_inline_entity_form_entity_form_alter` or `hook_field_widget_WIDGET_TYPE_form_alter` do the filtration job.

---
Tags: 8, entities
---


# Question
Title: How to change the label of an image's title field in a paragraph
In a paragraph I have an image field for which the title field is enabled and required. I need to alter the label of this title field to replace "Title" by "Caption"

I tried to use the `hook_field_widget_single_element_WIDGET_TYPE_form_alter()` to achieve this but all I see related to this title is

```
$element['subform']['image']['widget'][0]['#title_field'] = (bool) 1
$element['subform']['image']['widget'][0]['#title_field_required'] = (bool) 1

```

I am wondering how I can alter that label in this paragraph context. Any help would be appreciated.

# Answer
> 1 votes
I finally achieved what I wanted doing the following

**mymodule/mymodule.module**

```
use Drupal\Core\Form\FormStateInterface;
use Drupal\mymodule\Alter\FieldWidget\BlockImagesParagraph;

/**
 * Implements hook_field_widget_single_element_WIDGET_TYPE_form_alter().
 */
function mymodule_field_widget_single_element_entity_reference_paragraphs_form_alter(&$element, FormStateInterface $form_state, $context) {
  if ($element['#paragraph_type'] == 'block_images') {
    \Drupal::service('class_resolver')
      ->getInstanceFromDefinition(BlockImagesParagraph::class)
      ->alterFieldWidget($element, $form_state, $context);
  }
}

```

**mymodule/src/Alter/FieldWidget**

```
namespace Drupal\mymodule\Alter\FieldWidget;

use Drupal\Core\Form\FormStateInterface;

/**
 * Alter block_images paragraph.
 */
final class BlockImagesParagraph {

  /**
   * Alter the field widget.
   *
   * @param array $element
   *   The field widget form element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param array $context
   *   An associative array representing the context.
   */
  public function alterFieldWidget(array &$element, FormStateInterface $form_state, array $context) {
    $widget = &$element['subform']['image']['widget'];

    foreach ($widget as $key => &$value) {
      if (!is_int($key)) {
        continue;
      }
      $value['#process'][] = [
        'Drupal\mymodule\Alter\FieldWidget\BlockImagesParagraph',
        'processImageWidget',
      ];
    }
  }

  /**
   * Process the image widget.
   *
   * @param array $element
   *   The field widget form element.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form state.
   * @param array $form
   *   An associative array representing the form.
   */
  public static function processImageWidget(array $element, FormStateInterface $form_state, array $form) {
    if (isset($element['title'])) {
      $element['title']['#title'] = t('Caption');
    }

    return $element;
  }

}

```

---
Tags: forms, 9, paragraphs
---


title: How do I get the Unix timestamp?

text:
# Question
Title: How do I get the Unix timestamp?
I want to use `format_date()`, but it requires a Unix timestamp and my dates are ISO.

Is there a drupal way to convert ISO date to Unix timestamp? If I use strtotime, I lose my timezone offset.

# Answer
You shouldn't use `format_date()` anymore. You should create a `DrupalDateTime` object, and then use the `format()` method.

```
$date = \Drupal\Core\Datetime\DrupalDateTime::createFromFormat('c', $my_iso_8601_date);
$my_rfc2822_string = $date->format('r');

```
> 10 votes

# Answer
`format_date` deprecated in Drupal 8.0.0, will be removed before Drupal 9.0.0.

It's better to do it with Drupal way, using Drupal time service:

```
$time_value = \Drupal::time()->getCurrentTime();
print \Drupal::service('date.formatter')->format($time_value, 'long');

```
> 4 votes

# Answer
> I can't get it to work. This is what I'm passing: 2016-06-07T14:00:00, and I'd like to get this in return (except have it go through any timezone conversions): 1465308000

It's simple - you can use standard getTimestamp() function within the DrupalDateTime object:

```
$date = '2016-06-07T14:00:00';
$dateTime = new DrupalDateTime($date, 'UTC');
$timestamp = $dateTime->getTimestamp();

```
> 3 votes

# Answer
In Drupal 9 you can get the current timestamp using the following

```
use Drupal\Core\Datetime\DrupalDateTime;
$current_timestamp = (new DrupalDateTime())->getTimestamp();

```

DrupalDateTime is a wrapper over PHP DateTime object.
> 3 votes

# Answer
This is what I ended up using. I would like to experiment with MPD's solution more and will up date this question if I do.

```
$start_date = new DateTime($my_IOS_date, new DateTimeZone('UTC'));
$start_date->setTimezone(new DateTimeZone('America/New_York'));

$my_timestamp = $start_date->getTimestamp();

```
> 1 votes

---
Tags: 8, datetime
---


title: Can't save field translation

text:
# Question
Title: Can't save field translation
I have 2 languages on my site (English and Russian). I also have a content type "Home page" and some fields are translantable (configured in admin/config/regional/content-language)

After saving the content in russian translation, changes are saving in english and russian. What i have to do to save these fields for just one language?

Drupal version: 9.3.5

# Answer
You have an incorrect setup of the Drupal site/fields. Drupal will not override the other translations if fields translations are configured correctly. I suppose you use paragraphs and probably enable the paragraph reference fields translation instead of fields translations inside the paragraph. Need more input from your side about the problem.
> 1 votes

---
Tags: nodes, i18n-l10n
---


title: Render block in a view twig template

text:
# Question
Title: Render block in a view twig template
I need to render the output of a block within a view / node template (node--news--full.html.twig). Using {{ page.blockName }} does not return anything as {{ page }} within a node view simply returns a boolean (as expected within a node twig template).

Any ideas?

# Answer
The Twig Tweak module can print blocks:

```
{# Print block using default configuration. #}
{{ drupal_block('system_branding_block') }}

{# Print block using custom configuration. #}
{{ drupal_block('system_branding_block', {label: 'Branding', use_site_name: false, id}) }}

{# Bypass block.html.twig theming. #}
{{ drupal_block('system_branding_block', wrapper=false) }}

```

**Or use the views module itself**

In the views admin UI, you can add a block to the **Header**, **Footer**, or **No results behavior** areas. Just click **Add** and then select **Rendered entity - Block**.
> 4 votes

# Answer
Another possibility is to get the block to render array in views/node preprocess functions in theme/module and send it to the template through `$variables`.
> 0 votes

---
Tags: nodes, blocks, 9
---


# Question
Title: Private File Permissions Not Working for a Single file - Can't Identify where to find error
I have the following set up:

* Private file field configured on content type
* Access control configured with referenced user having permission to view file
* If user is referenced on the node, they can view the private file of that node.

Here is the issue that I am having:

* A specific file could not be loaded. Drupal Redirects as if the user does not have proper permissions to view the file.
* Other files, with an identical setup work fine
* If I download the file, rename it and re-upload to a new node, it works
* If I download the file, rename it and then re-upload on the original node it works

So, I have an intermittent issue where a tiny subset of files are not able to viewed by the user. What could possibly cause a single node/file combo to fail as described above?

# Answer
I suspect the problem is in the symbols of the file name. Probably, when PHP do the `file_exists` \- it may get false because the file is not 'visible'. Try this https://www.drupal.org/project/transliterate\_filenames or similar modules to transliterate the filenames during the uploads.

See more here File name transliteration
> 0 votes

---
Tags: nodes, files
---


title: How to have recurring date events?

text:
# Question
Title: How to have recurring date events?
It appears there is no End Date or Date Repeat options for the datetime field in Drupal 8.

Are there any contrib options for recurring events in Drupal 8?

# Answer
As of 2016/03/04, these are open issues in Drupal 8. See Support for end date and D8: Date repeat feature requests. The decision was made to move these from contrib into core, but they are complicated issues, and unfortunately touch the exact same portions of code, so working on them simultaneously is difficult.

As of 2016/12/07, support for end date is officially part of core, starting with 8.2.0. It is looking like the date repeat feature is going to end up in the datetime extras module as part of contrib, and not core. However, work on this is still preliminary.
> 9 votes

# Answer
There is a new module named Date Recur Field (repeating dates) that can help you.

> Recurring dates, i.e. date repeat, for Drupal 8.
>
> Provides a new field type that supports repeating dates via recurrence rules (RRule). For RRule compilation, php-rrule is used.

If you need integration with Calendar module you need to apply Patch for calendar module.

I think that the module needs integration with the Datetime Range core module because for the moment to show a multi days event in Calendar you need the Improve the Views integration for DateRange fields patch.
> 6 votes

# Answer
There's a sandbox: https://www.drupal.org/sandbox/frando/2775015 \- didn't test it, though.
> 3 votes

# Answer
You could use Recurring events

**Information about Recurring events**

The module allows site editors to create and manage events which recur in a variety of ways - including consecutively, daily, weekly, monthly, and custom recurrence configurations. An event series comprises of multiple event instances, each of which inherits data from the series, but can also be managed and viewed independently from the series itself, this offers great flexibility when it comes to modifying event instance dates and times or removing them altogether.

The module also has four submodules:

* recurring\_events\_registration enables registration for events
* recurring\_events\_views which swaps entity lists for flexible views
* recurring\_events\_reminders which allows sending of reminder emails for event registrants
* group\_recurring\_events\_series which allows the event series entities to be configured as groups with the Group module.

A part of edit form of event type
> 0 votes

---
Tags: 8, datetime
---


# Question
Title: Limit amount of adding a certain Paragraph per Content type
I use Drupal 8 Paragraphs module.

I created a `Content type` Landingpage.

I create some Paragraph types like `Hero Image`, `Intro text` etc.

In the `Content type` Landingpage I created a Paragraph `Entity reference revisions` field. In the `REFERENCE TYPE`, the Paragraph types `Hero Image`, `Intro text` are selected.

How do I manage the site editor is able to only insert one time (one value), the `Hero Image` Paragraph type? Because it doesn't make sense to have more then one Hero image section on the website...

# Answer
Things which only should be unique to a node, should better be attached directly to that node.

There's already a feature request on DO. But I'd recommend you to solve this by attaching these things directly to the node, with standard image or text fields.

```
-- node type
  |__ hero image field
  |__ intro text field
  |__ paragraphs field

```

The only other alternative I see is to add multiple Paragraphs fields to your content type and then limit them to only one type and one item.
> 2 votes

# Answer
Someone has since made a contrib module for this: Paragraphs Limits
> 0 votes

---
Tags: 8, entities, paragraphs
---


# Question
Title: What is the correct way to set language used by a modal form?
I have a button linked through a controller to open a custom form in a modal:

The controller callback is:

```
  /**
   * Callback for opening the modal form.
   */
  public function openShareLinkModalForm() {
    $response = new AjaxResponse();

    // Get the modal form using the form builder.
    $modal_form = $this->formBuilder->getForm('Drupal\ssc_wsl\Form\ShareLinkModalForm');

    // Add an AJAX command to open a modal dialog with the form as the content.
    $response->addCommand(new OpenModalDialogCommand($this->t('Share the link to this page.'), $modal_form, ['width' => '1200']));

    return $response;
  }
}

```

this works fine except that when my button is on a FR page, the modal still opens in EN.

From a trick I have used elsewhere, I tried adding this code in the callback just before the getForm() call:

```
$language_manager = \Drupal::languageManager();
$langcode = $language_manager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
$language = $language_manager->getLanguage($langcode);
$language_manager->setConfigOverrideLanguage($language);

```

This has no impact. The controller callback seems to be basing translation off the value in: $language\_manager-\>getCurrentLanguage(LanguageInterface::TYPE\_CONTENT) and that value is always the default value set for the site (if I set default site language to FR; then the modal only shows in FR).

The question is, is this the proper way to set the language used by the modal?

# Answer
> 1 votes
If language is by URL or path prefix, you'll need to make sure the AJAX call is to the correct URL or path prefix, to load the correct language.

---
Tags: forms, i18n-l10n, 9, modal-dialogs
---


# Question
Title: Can't preselect time zone in hook_form_alter
I'm writing a custom installation profile/distribution and I want to pre-populate some fields in the 'Configure Site' form (`/core/install.php`). I have managed to prefill/preselect other fields like (`Site name`, `Site email address` and `Default country`) but cannot preselect the `Default time zone` field. This is the code I am using:

```
function mydistribution_form_install_configure_form_alter(&$form, FormStateInterface $form_state) {
  $form['site_information']['site_name']['#default_value'] = 'Dummy Site Name';
  $form['site_information']['site_mail']['#default_value'] = 'example@example.com';

  $form['regional_settings']['site_default_country']['#default_value'] = 'DE';
  $form['regional_settings']['date_default_timezone']['#default_value'] = 'Europe/Berlin';
}

```

As you can see in the screenshot, I manage to change the `Default country` successfully, but not the `Default time zone`.

The "strange" thing though is that when I inspect the code, I can see that the correct timezone has been `selected` but the form displays `London`.

I'm based in the UK so I guess this is how London gets selected.

Does anyone know how to get this fixed? Thank you in advance!

# Answer
Drupal adds some JS to detect the timezone (through core/misc/timezone.js). This is interfering with your code, but can be removed easily:

```
unset($form['regional_settings']['date_default_timezone']['#attributes']);

```

This removes the `timezone-detect` class from the `<select>`, stopping it from being processed by the JS.
> 4 votes

---
Tags: forms, 9, installation-profiles
---


# Question
Title: How can I alter an order item field depending on inline entity form (IEF) validation?
I extended my order item type with an additional boolean field. Before the order item gets submitted via "order edit form" (*/admin/commerce/orders/{order\_id}/edit*), it should be validated and the boolean field should become "true" or remain "false".

The "order edit form" contains multiple inline entity forms (IEF). One of the IEF handles the order items of the order. I add a custom validation function with my custom module first:

```
function MYMODULE_inline_entity_form_entity_form_alter(array &$entity_form, FormStateInterface &$form_state)
{
...
array_unshift($entity_form['#element_validate'],'MYMODULE_inline_entity_form_validate_hide_gross_price');
...
}

```

The custom validation function is invoked successfully and the general business/process logic of the custom validation function is working fine too.

**The problem is, that I haven't found a way to set the value of my boolean field inside my order-item-type yet, depending on IEF validation.** I tried it with the `$form_state->setValueForElement()` API function (https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21FormStateInterface.php/function/FormStateInterface%3A%3AsetValueForElement/9.3.x):

```
function MYMODULE_inline_entity_form_validate_hide_gross_price(array &$entity_form, FormStateInterface $form_state) {
...
$form_state->setValueForElement($entity_form["field_MYFIELD_hide_gross_price"]["widget"]["value"],["#value"=> true]);
...
}

```

I get an error message

> This value should be of the correct primitive type. Drupal\Core\TypedData\Plugin\DataType\BooleanData: value

If I modify the code like following:

```
$form_state->setValueForElement($entity_form["field_MYFIELD_hide_gross_price"]["widget"]["value"]["#value"], true);

```

I get an PHP error in the watchdog logs:

> TypeError: Argument 1 passed to Drupal\Core\Form\FormState::setValueForElement() must be of the type array, int given

**So what is the correct syntax to set a boolean field value inside an order-item-type with IEF form?**

# Answer
I got the hint, that I used the wrong array elements. So it worked for me:

```
function MYMODULE_inline_entity_form_validate_hide_gross_price(array &$entity_form, FormStateInterface $form_state) {
...
$form_state->setValueForElement($entity_form["field_MYFIELD_hide_gross_price"]["widget"]["value"], true);
...
}

```
> 0 votes

---
Tags: entities, forms, commerce, 9
---


# Question
Title: How to add the domain to the Link field?
I activated the Link module that is part of Drupal core. I want to add on the user profiles fields with links to social pages and limit the domain used in the link.

How can I add such restriction to the link field?

I also tried the Social Media Links Block and Field module, but it uses a third-party library for the icons and it does not suit me.

I would like to make the link form elements appear like in the following screenshot.

>

# Answer
> 3 votes
I would do the following:

1. Implement hook\_field\_widget\_single\_element\_form\_alter(), and add an #element\_prefix key in front of the URL field with the domain. This will handle the display.
2. Create a custom validation constraint that limits the URL element of the Link field, and add it to the field on the user (using method #2 on the linked page).

---
Tags: entities, uri, 9, social-network
---


# Question
Title: Fields for different languages on the same interface
I have a node that has many fields but need only the title and body field translated.

This node type has a workflow associated to it and any authenticated user can create that node.

The client requires that fields for language EN/FR are all available on the form

I'm wondering what is the best approach to adopt: content translation + different fields for each language or Entity field translation

I've tried entity field translation but it does not provide the fields for each language on the same interface and it does not seem to work well with workbench moderation.

# Answer
> 3 votes
You must repeat the fields, because the Entity Translation and the Internationalization (i18n) module don't provive the fields for each language in the same interface.

# Answer
> 0 votes
Apparently there is a module for Drupal 7 called **Dual-language editor** (DLE) that does this.

For Drupal 8 and 9 there are 2 contrib modules:

Multilanguage Form Display: This tries to achieve the same thing by adding a form to translate all fields for each language. Seems that the module may not be stable enough, though.

Entity Translation Unified Form: I haven't used it yet, but this looks a bit more polished, has more usage and claims support for Paragraphs.

---
Tags: 7, nodes, i18n-l10n
---


# Question
Title: Key based access control for private files
I'm building a site that provides paid video content, for embedding in customer's own sites. I'm successfully controlling access to the nodes that contain the video content based on purchasable user roles.

Now I need to provide users with an embed code which ideally would only work from their domain. For now I'd be happy just to be able to limit it to specific users.

I have installed the key\_auth and restui modules, and I have enabled the 'file' REST resource. I can now access information \*about\* the file as an anonymous user with the paying subscriber's api key in the query. However I can't access the actual file.

The info I get back is below.

`{"fid":[{"value":3}],"uuid":[{"value":"5655ecda-b421-4ab8-aa92-d43c6c0fbfdf"}],"langcode":[{"value":"en"}],"uid":[{"target_id":1,"target_type":"user","target_uuid":"58d862eb-86e9-4ec6-bb33-89bda5c1767a","url":"\/user\/1"}],"filename":[{"value":"file_example_MP4_480_1_5MG.mp4"}],"uri":[{"value":"private:\/\/2022-04\/file_example_MP4_480_1_5MG.mp4","url":"\/system\/files\/2022-04\/file_example_MP4_480_1_5MG.mp4"}],"filemime":[{"value":"video\/mp4"}],"filesize":[{"value":1570024}],"status":[{"value":true}],"created":[{"value":"2022-04-16T15:52:39+00:00","format":"Y-m-d\\TH:i:sP"}],"changed":[{"value":"2022-04-16T15:52:43+00:00","format":"Y-m-d\\TH:i:sP"}]}`
How can I get access to the actual video in this way?

# Answer
I had to write a custom module with the following structure: `video_resource.info.yml
src/Plugin/Deriver/VideoDeriver.php
src/Plugin/rest/resource/VideoResource.php`

The rest resource and entity deriver are cut-down copies of the EntityResource and EntityDeriver:

`\Drupal\rest\Plugin\rest\resource\EntityResource
\Drupal\rest\Plugin\Deriver\EntityDeriver`

These classes together create a rest resource for every entity type. I set mine to only create a rest resource for the 'File' entity type, with the following code in its get() function:

`$filepath = $entity->getFileUri();
$response = new BinaryFileResponse($filepath);
return $response;`
> 0 votes

---
Tags: media, files, 9
---