TYPO3 backend button call php function/action - php

I've created a backend button in my extension which looks like this:
class ButtonBarHook {
public function getButtons(array $params, ButtonBar $buttonBar) {
$buttons = $params['buttons'];
$iconFactory = GeneralUtility::makeInstance(IconFactory::class);
$playController = new PlayController();
$button = $buttonBar->makeLinkButton();
$button->setIcon($iconFactory->getIcon('actions-document-export-csv', Icon::SIZE_SMALL));
$button->setTitle('Export als XML');
$button->setHref(***Link to my function***);
$buttons[ButtonBar::BUTTON_POSITION_LEFT][1][] = $button;
return $buttons;
}
}
So far so good. It appears in the backend of TYPO3. Now I want to link the button to call a php function I wrote in a different class. I already tried $button->setOnClick()but this only creates a javascript onClick event.
I think $button->setHref() is the better approach but I don't know what to put in here.
How can I link to my php function/action?

)
You have to link to a module or ajax route, that you have registered
https://docs.typo3.org/typo3cms/InsideTypo3Reference/CoreArchitecture/Backend/Routing/Index.html
And then you can use the method BackendUtility::getModuleUrl method to get a path to insert into setHref

Related

How to render a view in php and twig?

I'm creating a webpage where students and teachers log in, teachers create levels and students can do that level.
I explain, I am using php with twig and I want to render a view passing parameters in a function. I've created a budle called Professors where I have the directory Controllers, Models and Templates.
In templates I have professors.html, where I show some information and a button to create a level for students, and also I have crearNivell.html, where the teacher will be able to create the level. When I'm in the page views professors my URL is this one:
When I click the button "CREATE LEVEL" I want my URL to be like this:
Instead I get this URL, and this one returns me an error.
In Controllers/ProfessorsController.php I have that code:
class ProfessorController extends Controller{
public function process($params)
{
/*var_dump($params);
die();*/
if(empty($params[0])){
$this->getProfessor(); //Here I return the view professor
}elseif(isset($params[0]) && $params[0] == "crearNivell"){
$this->twig = "crearNivell.html";
}
}
public function getProfessor(){
$this->twig = "professor.html";
}
}
Can someone help me with my code?
When I use var_dump() I get this:
and it should be like that:
I think what you're looking for is the API of Twig.
More specifically, you need the line below to render a template passing some parameters in array:
echo $template->render(['the' => 'variables', 'go' => 'here']);
If you use PHP the fastest way to "print" some content to the browser is echo, so don't hesitate to use it.
I found the answer to the questions a few days ago. I was complicating myself, it's just like this:
First you create the views, in Templates folder.
The $params are refered to the URL. For example:
alumne is the bundle
AlumneController.php
Then in AlumneController.php put the name of the views without the .html and you show it using $this->twig = "name_Of_The_View.html";
<?php
class AlumneController extends Controller{
public function process($params)
{
/*var_dump($params);
die();*/
if(empty($params[0])){
$this->getAlumne();
/*echo $usuari = $_SESSION["username"];*/
}else if(isset($params[0]) && $params[0] == "instruccions"){
$this->twig = "instruccions.html";
/*echo $usuari = $_SESSION["username"];*/
}else if(isset($params[0]) && $params[0] == "resultats"){
$this->twig = "resultats.html";
/*echo $usuari = $_SESSION["username"];*/
}
}
public function getAlumne(){
$this->twig = "alumne.html";
}
}
alumne.html
And in the button or link you are using to go to the page you write the path in Instruccions
<a class="mdl-navigation__link" href="alumne/instruccions">Instruccions</a>
<a class="mdl-navigation__link" href="alumne/resultats">Resultats</a>

Generating CSV from CMS EditForm

I have a project where people can book places on events. There are dozens of events. I have been requested to generate a report listing attendees so they can be checked in at the door. Because there are so many events, I would like to add an "Attendees Report" button to the editform for each event (inside the CMS). I have created the button, and it works.
BUT... instead of getting the data in a CSV, I get the (correct) data displaying in the CMS, as if it was being echoed.
Here is my function
public function getCustomersForEvent($data, $form){
$attendees = CustomerOrderLine::get()->filter(array("EventID" => $data["ID"]));
if(!$attendees){
return false;
}
$fileName = "report.csv";
$separator = ",";
$csvColumns = array("ID", "Description", "Customer");
$fileData = "";
foreach($attendees as $row){
$fileData .= $row->Event()->EventName . $separator;
$fileData .= $row->CustomerOrder()->Customer()->FirstName . " " . $row->CustomerOrder()->Customer()->Surname . "\n";
}
return SS_HTTPRequest::send_file($fileData, $fileName, 'text/csv');
}
I have had a look at this http://www.silverstripe.org/community/forums/general-questions/show/15325 but the data echoed to the CMS anyway.
Can someone please tell me what I am doing wrong? As I said, the data is fine, but I'm not getting the CSV Open or Save dialog.
The solution will be in how you are calling this. I would advise that you make a complete new controller or modify a module like...
https://github.com/axyr/silverstripe-phpexcel
...where you can copy the php code and modify it to return just the data you require from above.
To make a controller that is only focused on downloading a file...
class CustomersForEvent_Controller extends Page_Controller {
private static $allowed_actions = array (
'downloadcsv',
);
public function downloadcsv() {
return SS_HTTPRequest::send_file("my content",'myfile.csv','text/csv');
}
}
and add that controller to the routes in _config/config.yml...
Director:
rules:
'attendees': 'CustomersForEvent_Controller'
...and then you can just link to yousite.com/attendees/downloadcsv
This has been tested locally and confirmed to work
Is this report to be generated from within the CMS itself? If so, do you have a ModelAdmin for managing CustomerOrderLine objects? If so, can you not use the GridField's "Export to CSV" button?
In order to output anything more than just those fields displayed by the GridField itself, you'll need to create/alter your model class's $getExportFields() method to return an array of all the fields on your model you wish to be exported in this manner.

Bolt CMS Events

I am working with the save event but having limited luck.
I have currently tried two ways but to limited success.
1) I can either never get the function to fire,
2) I am not too sure what to pass into the function for method two.
All I am trying to do is to dump the event information out on content save.Any help greatly appreciated, really loving this CMS
Attempt One -- never runs the function at all
class Extension extends BaseExtension
{
public function initialize() {
$this->addCss('assets/extension.css');
$this->addJavascript('assets/start.js', true);
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE, 'postSave');
}
function postSave(\Bolt\StorageEvent $event)
{
dump($event);
}
Attempt two -- what do I input as a parameter?
class Extension extends BaseExtension
{
public function initialize() {
$this->addCss('assets/extension.css');
$this->addJavascript('assets/start.js', true);
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE,$this->postsave($this->?????));
}
function postSave(\Bolt\StorageEvent $event)
{
dump($event);
}
Hopefully my answer doesn't come too late!
You simply can modify the content and save it back to the database:
public function postSave(\Bolt\Events\StorageEvent $event) {
// get the content
$content = $event->getContent();
// get a field out of the contenttype
$data = $content->get("myField");
// now modify $data here
$data = "new data - what ever you want";
// set data to the content
$content->setValue("data", $data);
// write the modified content to the database
$this->app['storage']->saveContent($content);
}
Note that the function gets fired every time you save contents. So just add an if-statement like this to just modify content you really want to:
if ($event->getContentType() == "my_type")
The parameter needed is a php callback the format for this is something like this:
$this->app['dispatcher']->addListener(\Bolt\Events\StorageEvents::POST_SAVE, array($this, 'postSave'));
That syntax is saying to run the postSave method within the current class. So this would work with your example number 1.
Now you can dump the event in your postSave method and see the results.

How set module view for custom searcher in prestashop 1.6

I'm trying to integrate Fotolia Api with Prestashop 1.6.0.9.
I already make module with custom tab, but I have no idea how set view from module folder for this tab. Sorry to say, but "documentation for developers" SUCKS.
I can't find any working solution.
public function install() {
if (!parent::install()
|| !$this->registerHook('backOfficeHeader')
|| !$this->registerHook('header')
) return false;
$tab = new Tab();
$tab->class_name = 'AdminFotoliaSelector';
$tab->id_parent = 0;
$tab->module = $this->name;
$tab->name[(int)(Configuration::get('PS_LANG_DEFAULT'))] = 'Fotolia Selector';
$tab->add();
return true;
}
I had big problem with make proper controller, and now I just can't load anything/ I have no idea how do this.
<?php
if (!defined('_PS_VERSION_'))
exit;
class AdminFotoliaSelectorController extends ModuleAdminController {
public $name;
public function __construct() {
$this->lang = (!isset($this->context->cookie) || !is_object($this->context->cookie)) ? intval(Configuration::get('PS_LANG_DEFAULT')) : intval($this->context->cookie->id_lang);
parent::__construct();
}
public function initContent() {
parent::initContent();
$this->renderForm();
}
public function renderForm() {
$path = _MODULE_DIR_."fotoliaselector";
$more = $this->module->display($path, 'views/templates/admin/fotoliaselector.tpl');
return $more.parent::renderForm();
}
When I try die($more) it gives me content of .tpl, anyway when I click tab in back office it's still empty.
I have debug options on, compiling on, cache off.
So just enlight me please, how am I supose to show ANYTHING there?
I think the problem is that you don't display tab's content at all.
I don't know what module->display method does, but I think you should change in initContent() method line:
$this->renderForm();
into
echo $this->renderForm();
If it won't help you should look at this documentation and try to do it without external classes - only try to use Smarty to display simple content without using Tab class or AdminFotoliaSelector
Well i know it will sounds weird but you need to take some similar modules, and read his code and will see some methods names are the same in each module.
Then copy that, install and play with some changes etc.
Imho you miss standard method getContent() form where you need to pass some data for smarty:
public function getContent()
{
global $smarty, $cookie;
......
//some code
......
$this->_html .= '<script type="text/javascript" src="'.__PS_BASE_URI__.'js/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>';
$this->_html .= '<h1>My module title or stuff</h1>';
$this->_html .= $this->getMyCoolFormOrConfig();
$smarty->assign('errors', $this->errors);
$smarty->assign('message', $this->message);
$this->_html .= $this->display(__FILE__, 'name_of_tpl_file.tpl');
return $this->_html;
}
to simple add tab in BackOffice code like this:
$id_tab=Tab::getIdFromClassName('AdminPayment');
$newtab=new Tab();
$newtab->id_parent=$id_tab;
$newtab->module=$this->name;
$newtab->class_name='MyClassName'; //will be same like MyClassName.php in folder of you module where you need to create you class and extend the AdminTab and from there with function you need to echo you name module
$newtab->position=Tab::getNbTabs($id_tab)+1;
$newtab->name[$cookie->id_lang]=$this->l("Name of you stuff");
$newtab->name[Configuration::get('PS_LANG_DEFAULT')]=$this->l("Name of you stuff");
$newtab->add();
Study this file there /controllers/admin/AdminModulesController.php
and you see what methods are using in each module
Take a look greater feature to generate you module structure (register requeired) https://validator.prestashop.com/generator

Cakephp calling function from view

I have the following function:
public function make_order($id = null){
if($this->request->is('post')){
if(isset($id)){
$single_product = $this->Product->find('first', array('Product.id' => $id));
$this->placeOrder($single_product);
}else{
$product_array = $_SESSION['basket'];
foreach($product_array as $product){
$this->placeOrder($product);
}
}
}
}
private function placeOrder($product){
$order_array = array();
$order_array['Order']['Product_id'] = $product['Product']['id'];
$order_array['Order']['lejer_id'] = $this->userid;
$order_array['Order']['udlejer_id'] = $product['users_id'];
$this->Order->add($order_array);
}
Now these two function are not "connected" to a view but i still need to call them from within another view
For this ive tried the following:
<?php echo $this->Html->link(__('Bestil'), array('action' => 'make_order')); ?>
However this throws an error saying it couldnt find the view matching make_order and for good reason ( i havnt created one and i do not intend to create one)
My question is how do i call and execute this function from within my view?
At the end of your make_order function, you'll either need to:
a) specify a view file to render, or
b) redirect to a different controller and / or action, that does have a view file to render.
a) would look like this:
$this->render('some_other_view_file');
b) might look like this (note: setting the flash message is optional)
$this->Session->setFlash(__('Your order was placed'));
$this->redirect(array('controller' => 'some_controller', 'action' => 'some_action'));
You can turn auto-rendering off by setting $this->autoRender = false; in your controller's action (make_order() in this case). This way you don't need a view file, and you can output whatever you need.
The problem is that nothing will be rendered on the screen. Therefore, my advice is to have your "link" simply call a controller::action via AJAX. If that's not possible in your situation, then you'll have to either render a view in your make_order() method, or redirect to an action that will render a view.

Categories