Save charts on server - symfony

I have a symfony3 project with working Highcharts functions implemented through the ob/highcharts-bundle and I really like the way the generated charts look with a custom theme.
I would like to be able to run a script on the server that generates an email and along the way builds the charts that I need (complete with my custom theme) and saves to the server so I can link to them from the email.
I've previously done this in pChart, and saving an image on the server from a script is as easy as $myPicture->autoOutput('myimage.png'). While that's easy, I prefer the look of charts from Highcharts.
Is there a similar simple way to do this something like this using Highcharts?
My scripts look like this:
// Controller
$xdata = array(1, 2, 3, 4);
$data_series = array(
0 => array(
"name" => "Series 1",
"data" => array(
0 => 2.0, 1 => 0.0, 2 => 5.0, 3 => 2.3, 4 => 0.45, 5 => 0.4
)
)
);
$ob = new Highchart();
$ob->chart->renderTo('trendchart'); // id of the div where the chart gets rendered
$ob->title->text('Chart title');
$ob->xAxis->categories($xdata);
$ob->series($data_series);
return $this->render('dashboard/main.html.twig', [
'trendChart' => $ob,
]);
and I render this in a twig template:
// twig template
{% extends 'base.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="//code.highcharts.com/highcharts.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
<script src="{{ asset('js/highchartThemes/mytheme.js') }}"></script>
<script>
{{ chart(trendChart) }}
</script>
{% endblock %}
{% block body %}
<div id="trendchart"></div>
{% endblock %}
What I'm hoping for is to make a call from my controller like:
$ob->save('myimage.png');
Does anyone know of a simple/clean way to do something like this?

Related

How do I pass variables to theme template via custom controller drupal 8

I currently have a theme I purchased installed on my Drupal website.
Inside the theme folder there is a templates folder that contains:
page.html.twig
page--front.html.twig
a snippet from page.html.twig looks as follows:
<footer class="site-footer">
<div class="layout-container">
{% if page.footer_first or page.footer_second or page.footer_third %}
<div class="footer-top">
<div class="footer-top-inner">
{{ page.footer_first }}
{{ page.footer_second }}
{{ page.footer_third }}
</div>
</div>
{% endif %}
{% if page.footer_left or page.footer_right %}
<div class="footer-bottom">
<div class="footer-bottom-inner">
{{ page.footer_left }}
{{ page.footer_right }}
</div><!-- /.footer-bottom-inner -->
</div>
{% endif %}
</div>
</footer>
I have a custom module I created (business_listing) that loads different .html.twig templates I add these templates in business_listing.module:
function business_listing_theme($existing, $type, $theme, $path) {
return [
// business-listing-detail.html.twig
'business_listing_detail' => [
'variables' => ['data' => [], 'slides' => [], 'paths' => [], 'page' => []],
],
]
}
Basically I would like to know how I can add the markup for the footer dynamically from my custom modules controller.
I have a page called business-listing-detail.html.twig inside my custom modules templates folder. From what I understand business-listing-detail.html.twig uses/somehow extends page.html.twig in my theme/templates. What I would now like to know is how I can add the sections like {{page.footer_left}} to my business-listing-detail.html.twig or to page.html.twig using my controller? I have tried adding the footer using the following: `
$page['footer_left'] = "This should appear in the .footer-bottom div?";
$build = [];
$build['business_listing_detail'] = [
'#theme' => 'business_listing_detail',
'#data' => $record,
'#slides' => $slides,
'#paths' => $this->paths,
'#page' => $page
];`
in the controller function associated to my business-listing-detail page the hopes that page.html.twig will detect this page.footer_left and render display the footer, however this did not work. The variable exists in business-listing-detail.html.twig but the {% if page.footer_left %} in my themes page.html.twig is not fired. Please please please, any help or advice would be greatly appreciated <3
Basically all I am trying to do, is dynamically render a template for a specific page in my custom module, that allows me to implement/send markup to the sections/regions defined in my theme eg. featured_top, content_top & page.content
Kind regards,
Matt
It seems like you might be going down the wrong path... I'd highly suggest you read up about the Drupal 8 Block system, and then investigate custom blocks.

How to Embed Controllers in a Template using Symfony 4 directory structure

I did a fresh Symfony installation by using Symfony Flex and the new skeleton belong to the next Symfony 4 directory structure. Next, I'm going to embed a controller from a twig template.
I've tried to do it like this:
<div id="sidebar">
{{ render(controller(
'App:Article:recentArticles',
{ 'max': 3 }
)) }}
</div>
The same with How to Forward Requests to another Controller, I've tried:
$response = $this->forward('App:Something:fancy', array(
'name' => $name,
'color' => 'green',
));
But is not working.
There is way to do this?
When we using the short convention a:b:c to refer to the controller, it will only work if the controller belong to an installed bundle. For Symfony 4 structure your app source is not a bundle by default, so the above does not work.
For Symfony 4 approach you can refer to this controller using its fully-qualified class name and method:
App\Controller\ArticleController::recentArticlesAction
Embedding the controller into Twig templates:
{{ render(controller('App\\Controller\\ArticleController::recentArticlesAction')) }}
This is the correct way to do this:
{# templates/base.html.twig #}
{# ... #}
<div id="sidebar">
{{ render(controller(
'App\\Controller\\ArticleController::recentArticles',
{ 'max': 3 }
)) }}
</div>
Source: https://symfony.com/doc/master/templating/embedding_controllers.html

Symfony3 Highcharts pie chart blank

I started with Highcharts today in a symfony3 project and have the line charts working great. I'm having trouble rendering a pie chart and I'm beating my head on the wall trying to figure out why it's not working.
I can reproduce the basic pie chart (like this one) if I render directly in javascript in my twig template, and it looks as expected. BUT if I try to render from my controller I get a blank image where the pie chart should be. My chart title is there so I know I'm rendering to the correct div. But the chart is blank. I've even tried very simple data structures (like an array of numbers as suggested by the docs) with no luck. This must be something simple. Help!
My controller:
public function piechartAction()
{
$data = [["name"=> 'Microsoft Internet Explorer', "y"=> 56.33],
["name"=> 'Chrome', "data"=> 24.03],
["name"=> 'Firefox', "y"=> 10.38],
["name"=> 'Safari', "y"=> 4.77],
["name"=> 'Opera', "y"=> 0.91],
["name"=> 'Proprietary or Undetectable', "y"=> 0.2]];
$ob = new Highchart();
$ob->chart->renderTo('container');
$ob->chart->type('pie');
$ob->title->text('My Pie Chart');
$ob->series(array("data"=>$data));
return $this->render('dashboard/test.html.twig', [
'mypiechart' => $ob
]);
}
And my twig template:
{% extends 'base.html.twig' %}
{% block javascripts %}
{{ parent() }}
<script src="//code.highcharts.com/highcharts.js"></script>
<script src="//code.highcharts.com/modules/exporting.js"></script>
<script>
jQuery(document).ready(function() {
{{ chart(mypiechart) }}
});
</script>
{% endblock %}
{% block body %}
<div id="container" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
{% endblock %}
I solved this. For anyone looking in the future, here's what I had wrong:
My setting of series data was not the correct format.
Here's my new (working) controller:
public function piechartAction()
{
$data = [
['Microsoft Internet Explorer', 56.33],
['Chrome', 24.03],
['Firefox', 10.38],
['Safari', 4.77],
['Opera', 0.91],
['Proprietary or Undetectable', 0.2]
];
$ob = new Highchart();
$ob->chart->renderTo('container');
$ob->chart->type('pie');
$ob->title->text('My Pie Chart');
$ob->series(array(array("data"=>$data)));
return $this->render('dashboard/test.html.twig', [
'mypiechart' => $ob
]);
}
I found this by studying the "cookbook" associated with this bundle (here); there is a listing for a drill-down pie chart.

Symfony - pass custom data from Form Builder to form theme

I would like to set a special div surrounding a bunch of my fields. For that I want to add something to the form builder that I could detect in my form_theme, and set the div when it's there.
I tried to add
->add('field', new myCustomType(), array('inherit_data' => true, "label" => false, "required" => false, 'attr' => array("test" => "aaa")))
to the form builder, setting an custom attr, it's actually rendered in the html as an attribute... But I'm unable to detect it in the form theme.
{{ block('widget_container_attributes') }}
Only gives the widget attributes, and
{{ block('row_container_attributes') }}
doesn't work. I actually have a hard time finding any source online about what variables are available in the blocks of the form theme and how to use them (it was already difficult to know how to call blocks).
I looked for some more information on the official site, here mostly but without any success...
Thanks ahead for any help !
If you put it in your form builder, then you might as well permanently set in your template. If there is some logic required to set the data, then that belongs in your controller anyway, so just put it there to start with.
Controller:
public function someAction()
{
// ....
return $this->render('some_twig_template.twig.html', array(
'attr' => array("test" => "aaa")
);
}
Then in your twig template
{{ dump(attr) }}
{{ dump(attr.test) }}
EDIT:
To render in your template every time, you can set a class on the rendered field directly:
{{ form_label(form.field, 'My label', { 'label_attr': {'class': 'js-hidden-row'} }) }}
{{ form_widget(form.field, { 'attr': {'class': 'js-hidden-row'} }) }}
Then in my javascript you can hide with some simple jQuery:
<script>
jQuery(document).ready(function() {
$('.js-hidden-row').hide();
});
</script>

Using twig translations inside Moustache inside Twig

I have a moustache template inside my twig template. I use the moustache template in javascript and it contains some text and JS variables.
{# _partial.html.twig #}
{% verbatim %}
<script id="insuranceOptionTpl" type="text/template">
{{ #. }}
<strong>My template is {{ adjective }}</strong>
{{ /. }}
</script>
{% endverbatim %}
Now I need to internationalize this page but my twig translations won't work inside verbatim. Is there any elegant ways to do that? I will probably have many different texts to translate, so ending and starting a new verbatim block all the time is not ideal.
By removing the verbatim block and by customizing Twig delimiters to be differents than Mustache ones, replacing {{ and }} by [[ and ]] for example (as explained in Twig doc), you'll be able to use Twig and Mustache in the same template:
$twig = new Twig_Environment();
$lexer = new Twig_Lexer($twig, array(
'tag_comment' => array('{#', '#}'),
'tag_block' => array('{%', '%}'),
'tag_variable' => array('[[', ']]'),
'interpolation' => array('#{', '}'),
));
$twig->setLexer($lexer);
As most of your templates are already in Twig, you can change Mustache delimiters instead:
$(document).ready(function () {
var output = $("#output");
var template = $("#insuranceOptionTpl").html();
//Custom tags for Mustache
var customTags = [ '[[', ']]' ];
Mustache.tags = customTags;
// render string
var data1 = "Hello world!";
var html = Mustache.render(template, data1);
output.append(html);
});

Resources