I am trying to sort of reverse engineer to this twig template to get back to where the the variables are being set in the first place so I can add more variables. This is a Drupal8 project. The beginning of the twig template "node--course.html.twig" is seen below. Its where I see the variables being set.
{#
/**
* #file
* Default theme implementation to display a node.
*
* Available variables:
* - node: Full node entity.
* - id: The node ID.
* - bundle: The type of the node, for example, "page" or "article".
* - authorid: The user ID of the node author.
* - createdtime: Time the node was published formatted in Unix timestamp.
* - changedtime: Time the node was changed formatted in Unix timestamp.
* - label: The title of the node.
* - content: All node items. Use {{ content }} to print them all,
* or print a subset such as {{ content.field_example }}. Use
* {{ content|without('field_example') }} to temporarily suppress the printing
* of a given child element.
* - author_picture: The node author user entity, rendered using the "compact"
* view mode.
* - metadata: Metadata for this node.
* - date: Themed creation date field.
* - author_name: Themed author name field.
* - url: Direct URL of the current node.
* - display_submitted: Whether submission information should be displayed.
* - attributes: HTML attributes for the containing element.
* The attributes.class element may contain one or more of the following
* classes:
* - node: The current template type (also known as a "theming hook").
* - node--type-[type]: The current node type. For example, if the node is an
* "Article" it would result in "node--type-article". Note that the machine
* name will often be in a short form of the human readable label.
* - node--view-mode-[view_mode]: The View Mode of the node; for example, a
* teaser would result in: "node--view-mode-teaser", and
* full: "node--view-mode-full".
* The following are controlled through the node publishing options.
* - node--promoted: Appears on nodes promoted to the front page.
* - node--sticky: Appears on nodes ordered above other non-sticky nodes in
* teaser listings.
* - node--unpublished: Appears on unpublished nodes visible only to site
* admins.
* - title_attributes: Same as attributes, except applied to the main title
* tag that appears in the template.
* - content_attributes: Same as attributes, except applied to the main
* content tag that appears in the template.
* - author_attributes: Same as attributes, except applied to the author of
* the node tag that appears in the template.
* - title_prefix: Additional output populated by modules, intended to be
* displayed in front of the main title tag that appears in the template.
* - title_suffix: Additional output populated by modules, intended to be
* displayed after the main title tag that appears in the template.
* - view_mode: View mode; for example, "teaser" or "full".
* - teaser: Flag for the teaser state. Will be true if view_mode is 'teaser'.
* - page: Flag for the full page state. Will be true if view_mode is 'full'.
* - readmore: Flag for more state. Will be true if the teaser content of the
* node cannot hold the main body content.
* - logged_in: Flag for authenticated user status. Will be true when the
* current user is a logged-in member.
* - is_admin: Flag for admin user status. Will be true when the current user
* is an administrator.
*
* #see template_preprocess_node()
*
* #todo Remove the id attribute (or make it a class), because if that gets
* rendered twice on a page this is invalid CSS for example: two lists
* in different view modes.
*
* #ingroup themeable
*/
#}
{# {{ kint() }} #}
<article id="node-{{ node.id }}" {{ attributes }}>
{{node}}
{{ title_prefix }}
{% if not page %}
<h2{{ title_attributes }}>
{{ label }}
</h2>
{% endif %}
{{ title_suffix }}
{% if node.field_packaging.value == '1' %}
{% set image = content.field_image %}
{% set ce = content.field_tax_credit_hours %}
{% set goal = content.field_goal %}
{% set target_audience = content.field_audience %}
{% set objectives = content.field_objectives %}
{% set accreditation = content.field_accreditation %}
{% set disclosure = content.field_disclosure_statement %}
{# {% set references_old = content.field_references %} #}
{% set references = content.field_references_par %}
{% set appendix = content.field_appendix %}
{% set faculty = content.field_faculty %}
{% set related_courses = content.field_related_courses %}
{# set suggested_courses = content.field_suggested_courses #}
{% set additional = content.field_callout %}
{% set expiration = node.field_expiration.value %}
I have tried taking words that appear to be unique like
field_tax_credit_hours
And search the project to see maybe where its being set but it only appears in other twig files. I also looked at the whole page as a whole to see maybe I can search for where the output is coming from. For example they very start of my page begins with:
<!-- returning result -->
When I search that it points me to a php function called getResult()
public function getResult() {
if ($this->rowBase() == "") {
print "<!-- rowBase empty -->";
\Drupal\Core\Database\Database::setActiveConnection();
return false;
}
print "<!-- returning result -->";
$result = $this->connection->query($this->rowBase())->fetchAll();
\Drupal\Core\Database\Database::setActiveConnection();
return $result;
}
searching for rowBase() i found this function:
public function rowBase() {
if (parent::accessCheck()) {
$sql = "SELECT * FROM learning_courseuser
WHERE idUser = " . $_SESSION['public_area_idst'] .
" AND idCourse = " . $this->ID. " ";
return $sql;
} else {
return "";
}
}
So it appears to not set the variables I need but instead returns the users info if the are logged in. So I am now stuck and don't really know where to go from here. I have been a PHP developer for a year or so and only did a team treehouse drupal course so it was very basic.
I noticed the page also returns this
<!-- BEGIN OUTPUT from 'themes/custom/site/templates/node--course.html.twig' -->
But searching for the string "BEGIN OUTPUT" returns nothing. So I don't know where to go from here.
It seems that the variables are coming from the "content" object but searching content in the project has WAY too many results to go through. Any ideas where to look would be fantastic.
UPDATE
I was asked to look into template_preprocess_node
and got this:
function site_preprocess_node(&$variables) {
$node = \Drupal::routeMatch()->getParameter('node');
if ($node && $node->getType() == 'course') {
$noti = new FormaNotification();
print "HERE";
print_r($noti->getResult());
exit;
if ($noti->getResult()) {
$variables['signIn'] = "yes";
if ($noti->getFormaAdmin())
$variables['is_forma_admin'] = "yes";
else
$variables['is_forma_admin'] = "no";
} else {
$variables['signIn'] = "no";
$variables['is_forma_admin'] = "no";
}
$current_url = Url::fromRoute('<current>');
$variables['signURL'] = 'http://' . $_SERVER['HTTP_HOST'] . $current_url->toString();
if ($node->get('field_packaging')->getValue()[0]['value'] == '2') {
$variables['regis'] = true;
} else {
$reg = new FormaRegis();
$reg->setConnection('docebo');
$reg->setID($node->get('field_docebo_course_id')->getValue()[0]['value']);
$result = $reg->getResult();
if(!empty($result)) {
$variables['regis'] = true;
} else {
$variables['regis'] = false;
}
}
} // course
}
So looking at it, it appears to have some function of registration sign in and not the variables
The answer is into CMS.
The machine name starting with field_* usually is made when you create a new field into a content type on CMS.
Login into cms (/user) and search for structure-> content types -> (your content types) and then manage fields.
You should find it.
Related
I'm using Symfony 6.1 with Twig on PHP 8.1. I've already set up my complete layout including fragments/partials/components or whatever we call reusable pieces of the layout at the moment. These fragments include certain kinds of navigations, quotes, tabs and so on which are always supposed to look and work the same and usually only receive a variable with the same name as an array with a few options.
This is how I'm embedding a YouTube-Video for example:
{% set youtube_video = { 'id': 'dQw4w9WgXcQ', 'title': 'Secret Video (unlisted)', 'language': 'en' } %} {% include 'fragment/youtube_video.html.twig' %}
Most of these fragments can be used multiple times on one page (= in the main template of the view or within the base template/s). Some of them however are supposed to be used only once and using them multiple times would create layout issues (e.g. a navigation for mobile devices with a specific CSS id).
For other fragments I would like to have a counter to add a CSS id in addition to a normal class:
<div class="fragment_video" id="fragment_video_{{ counter }}> ... </div>
The question now is how I can count within a fragment template like 'fragment/youtube_video.html.twig' how often this template has been used in that page already. I don't see any Twig functions or anything within the "app" variable for that.
Now I could create a custom Twig function "counter" and call that with with a unique name:
<div class="fragment_video" id="fragment_video_{{ counter('fragment_video') }}> ... </div>
or
{% if counter('fragment_video') == 1 %} ... {% endif %}
BUT how would I store the current count per given name? I don't want to use $GLOBALS in Twig or rather Symfony and storing that information in the session would keep it past the current request. Is there another solution available?
This is how it would look like as a Twig function:
public function getCounter(string $name): int
{
$name = 'twig_counter_'.$name;
if (isset($GLOBALS[$name])) {
++$GLOBALS[$name];
} else {
$GLOBALS[$name] = 1;
}
return $GLOBALS[$name];
}
As suggested by #DarkBee the instance of a TwigExtension object can use properties to keep track of some information:
/**
* #var array<int>
*/
private array $count = [];
...
public function getCounter(string $name): int
{
if (isset($this->count[$name])) {
++$this->count[$name];
} else {
$this->count[$name] = 1;
}
return $this->count[$name];
}
I'm having trouble returning an array of options from an SQL database. I've tried a few different variations of returning the data, but I can only seem to get single data points returning like radio buttons, input text, etc.
I have 3 checkboxes in a form: Blue car, Red car, Green car.
They all save to the database. However, a "1" is been added. eg. [Blue car, Red car, 1] is being stored.
When I try and return the data to the twig template, it doesn't load anything.
I'm new to twig and Symfony, and I'm partly learning through existing code which makes it hard for me to troubleshoot sometimes.
I'm looking for the output to be like this: Blue car (or) Blue car & Red car (or) Blue car, Red car & Green car. Happy for the code to be simplified for this output.
var
/**
* #var string
*
* #ORM\Column(name="sel_cars", type="string", length=255, nullable=false)
*/
private $sel_cars;
/**
* Get cars
*
* #return string
*/
public function getSelcars()
{
return $this->sel_cars;
}
/**
* Set cars
*
* #param string $sel_cars
*
* #return Listing
*/
public function setSelcars($sel_cars)
{
$this->sel_cars = $sel_cars;
return $this;
}
output
{% if item.sel_cars is not empty %}
{% set sel_cars = item.sel_cars|split(',') -%}
{% set sel_carsarray = { 'bluecar': 'Blue car', 'redcar': 'Red car', 'greencar': 'Green car'} %}
{% for row in sel_cars %}
{{ sel_carsarray[row] }}
{% endfor %}
{% endif -%}
Appreciate the help :)
I seemed to have figured it out.
changing all the above output code from
item.sel_cars
to
item.Selcars
It now returns the data.
is there a way to get the current route {placeholder} value in symfony?
I have :
/**
* #Route("/ideas/{page}",
* defaults={"page":1},
* requirements={"page":"^\d+$"},
* name="ideas")
*/
public function ideasAction($page) {
.....
return $this->render('idea/idea.html.twig', ["ideas" => $ideas]);
}
And in my twig I want to do something like this :
>
Is it possible?
Like Gara said :
With {{ app.request.get('page') + 1 }} you can get your placeholder
So this works :
{% set page = app.request.get('page') + 1 %}
>
I'm having a hell of a time trying to get classes on my body element in D8. I'm using a custom theme and the code I have so far looks like this:
themename.theme
use Drupal\Component\Utility\Html;
/**
* Preprocess variables for html templates.
*/
function HOOK_preprocess_html(&$variables) {
$path_class = !$variables['root_path'] ? 'path-frontpage' : 'path-' . Html::getClass($variables['root_path']);
if (isset($path_class)) {
$variables['attributes']['class'][] = $path_class;
}
}
html.html.twig
{%
set body_classes = [
not root_path ? 'path-frontpage' : 'path-' ~ root_path|clean_class,
]
%}
<body{{ attributes.addClass(body_classes) }}>
I get classes on my body element, but the NID is empty, reading, 'page-node' where I need it to read, 'page-node-NID'.
You have to replace HOOK with the name of your theme mytheme_preprocess_html otherwise Drupal will not call the hook.
I import the Bundle AliDatatableBundle on github following the doc step one by one except the part $ bin/vendor install in the installation because with Symfony2.6, there's no need to do this.
When I create the function in my controller, and the rendering in my twig, I have this error:
An exception has been thrown during the rendering of a template ("No
instance found for datatable, you should set a datatable id in your
action with "setDatatableId" using the id from your view ") in
MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig at
line 37.
Here's the code for the controller:
/**
* set datatable configs
*
* #return \Ali\DatatableBundle\Util\Datatable
*/
private function _datatable()
{
$controller_instance = $this;
return $this->get('datatable')
->setDatatableId('batiments')
//->setEntity("MySpaceDatabaseBundle:Batiments", "b")
// replace "XXXMyBundle:Entity" by your entity
->setFields(
array(
"Nom" => 'b.nom',
// Declaration for fields:
"Reférence" => 'b.referencebatiment',
// "label" => "alias.field_attribute_for_dql"
"Ensembles" => 'b.ensembles',
"_identifier_" => 'b.id')
// you have to put the identifier field without label. Do not replace the "_identifier_"
)
//->setWhere(
// set your dql where statement
//'x.address = :address',
//array('address' => 'Paris')
//)
//->setOrder("x.created", "desc")
// it's also possible to set the default order
->setHasAction(true);
// you can disable action column from here by setting "false".
}
/**
* Grid action
* #return Response
*/
public function gridAction()
{
return $this->_datatable()->execute();
// call the "execute" method in your grid action
}
/**
* Lists all entities.
* #return Response
*/
public function indexAction()
{
$this->_datatable();
// call the datatable config initializer
return $this->render('MySpaceGestionPatrimoinesBundle:Batiments:indexBatiments.html.twig');
// replace "XXXMyBundle:Module:index.html.twig" by yours
}
And then the code for my twig:
{% extends "MySpaceWelcomeBundle::layout.html.twig" %}
{% block content %}
<div class="jumbotron">
<h4><u>Rechercher un bâtiment et ses affectations spécifiques:</u></h4>
<br>
<div>
{{ datatable({
'id' : 'batiments',
'js' : {
'sAjaxSource' : path('mySpace_formulaire_recherche_batiments')
}
})
}}
</div>
</div>
{% endblock %}
I really don't understand, someone could help me to fix this?
I have already clear the cache, install assets and took over again from the beginning the doc, I do not understand.
Thank you in advance.
It seems like everything was good. I can't see the problem here, if you followed the doc of aliBundle. Try using the Jquery datatable here, the installation is easier I think and better for your project if it's to manage your entities in Symfony.
If you have questions for Jquery DataTables, don't hesitate to ask, I'm using it for a Symfony project too.