MVCGRID CSV Export error - php

i'm trying to export a grid i create with the object MVCgrid.
I found out that i can add the the current page the object 'MVCGrid_Export' instead of the object 'MVCGrid'that provides the export buttons and functionalities.
By the way i got an error during the export :
"Fatal error: Call to a member function getField() on a non-object in ..\agiletoolkit\atk4-addons\misc\lib\Export.php on line 42"
At that line, "$b[] = $this->__getHeaderModel()->getField($a)->caption();", i discovered that the result of "$this->_getHeaderModel()" is a string of the model i want to export, and not the object of that model , that is the item i need.
This is the code of my page:
class page_resultsShow extends Page {
function initMainPage() {
$p = $this;
$gr = $this->add('MVCGrid_Export');
$gr->setModel('results',array('name','budget','bestapplicants'));
$gr->addColumnMVC('name');
$gr->addFormatter('name','link');
$gr->addQuickSearch(array('name'));
$gr->addPaginator(20);
}
//details...
function page_details() {
... some code..
}
function defaultTemplate(){
return array('page/results');
}
}
I suppose i need to add some informations to explain to the grid the model that is handling , but i didn't find how!!
Thank you for the help

We have pushed updated export module for 4.2
Please, update atk4-addons and atk4 to make sure you are on master branch (which is now 4.2).
syntax is a bit different now, as Export now acts as controller.
class page_index extends Page {
function init(){
parent::init();
$c=$this->add("Grid");
$c->setModel("A");
$c->addPaginator(1);
$c->add("Export");
$c=$this->add("CRUD");
$c->setModel("A");
if ($c->grid){
$c->grid->addPaginator(1);
}
$c->add("Export");
}
}
From email to atk4 group:
// let's say you have grid
$export = $grid->add("Export");
// this would add export xls & export csv buttons to your grid
// if you have crud:
$export = $crud->add("Export");
// this would add export xls & export csv buttons to your grid
Now, you can easily create new "Parsers", by creating
Export_Parser_Xyz class.
then just add it to your export:
$export->add("Export_Parser_Xyz");
very important update is that it now uses dq after it has been altered by paginators, filters etc. so that it would export exactly what is displayed. Optional, is limit which by default is being removed, but can be controlled on a parser level.
this would automatically add button to grid/crud and handle data flow from respective grid/crud data source.
N.B.!
Export works only with dq based Grid and, if model is defined, attempts to load captions from model's field definitions.
PDF parser is left out at this point, as it was very specific and required specific 3rd party software.
Should you want to have old Export module follow instructions in lib/Export.php to enable compatibility mode.

Related

TYPO3 EXT:cart_product: extend class product with own extension

I try to extend the existing class Product from the Typo3 (Version 11) cart_products extension with my own extension. Therefor I have already extended the backend and tables to store a new value called productpackagetype.
Next step for me was to implement the new class Product in myext/Classes/Domain/Model/Product/Product.php which looks like this :
<?php
namespace Vendor\myext\Domain\Model\Product;
class Product extends \Extcode\CartProducts\Domain\Model\Product\Product
{
protected $productpackagetype = '';
public function getProductpackagetype()
{
return $this->productpackagetype;
}
public function setProductpackagetype($productpackagetype)
{
$this->productpackagetype = $productpackagetype;
}
}
To tell typo3 to use the new class definition I tried the following code in the myext/ext_localconf.php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\Extcode\CartProducts\Domain\Model\Product\Product::class] = [
'className' => \Vendor\myext\Domain\Model\Product\Product::class
];
\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\Container\Container::class)
->registerImplementation(
\Extcode\CartProducts\Domain\Model\Product\Product::class,
\Vendor\myext\Domain\Model\Product\Product::class
);
As long as I write nothing to myext/ext_localconf.php nothing in the frontend changes. But as soon as I add the above code typo3 comes up with a Error 503
Return value of Extcode\CartProducts\Domain\Model\Product\Product::getBeVariants() must be an instance of TYPO3\CMS\Extbase\Persistence\ObjectStorage, null returned
So what would be the right way to bring up my extended class. And maybe someone can tell me how I tell typo3 to use my extensions private template show.html instead of using cart_products template.
Best regards
Johannes
You forgot to map your model to the products table of the extension cart_products. To do so, create a file myext/Configuration/Extbase/Persistence/Classes.php and paste these lines:
<?php
declare(strict_types = 1);
return [
\Vendor\myext\Domain\Model\Product\Product::class => [
'tableName' => 'tx_cartproducts_domain_model_product_product',
],
];
You need to flush all the caches to apply this change.
You can read more about persistence handling in TYPO3 here.
Concerning your second question: You have to configure the paths to your templates in TypoScript:
plugin.tx_cartproducts {
view {
templateRootPaths.10 = EXT:myext/Resources/Private/Templates/
partialRootPaths.10 = EXT:myext/Resources/Private/Partials/
layoutRootPaths.10 = EXT:myext/Resources/Private/Layouts/
}
}
Please note the index 10 here. You can configure multiple paths. TYPO3 will start looking for the template in the folder configured with the hightest numbered index. If the file does not exist at that location, it continues with the next lower index.
When you inspect the file cart_products/Configuration/TypoScript/setup.typoscript you will see that the extension uses the index 0. So if you don't provide any templates, the default ones will be used.
Make sure to use the same names for folders and files as in the original extension.
You can read more about template paths in TYPO3 here

Silverstripe Elemental Module redirects to frontend 404 page on element save

I use dnadesign/silverstripe-elemental 2.x-dev, and Silverstripe 4.0.1.
I created a module for page to hold all pages. This is how i added the extension to HomePage.
XYPage\Model\HomePage:
extensions:
- DNADesign\Elemental\Extensions\ElementalPageExtension
This is my HomePageController:
namespace XYpage\Controller;
use PageController;
class HomePageController extends PageController
{
}
This is my HomePageModel:
namespace XYpage\Model;
use Page;
use XYpage\Controller\HomePageController;
class HomePage extends Page
{
private static $table_name = 'HomePage';
/**
* As our controller resides in a different namespace we have to
overwrite this method
*
* #return string
*/
public function getControllerName()
{
return HomePageController::class;
}
}
I changed the template variable to $ElementalArea. I see the expected UI in the BackEnd.
Now if i save an single element in the backend i always get redirected into the front-end to the 404 Page.
When i switch back to the Backend the element is linked to the page.
If i fill in content to the WYSIWYG editor on the Content Element and save it the content gets displayed on the page in the frontend.
If i try to edit that element misses the WYSIWYG editor for the content.
I tried hard to fix this, red the docs but i don´t see what i did wrong.
There is an issue with BetterButtons & DNADesign Elemental.
Just add this to disable BetterButtons for ElementContent in the meantime.
DNADesign\Elemental\Models\ElementContent:
better_buttons_enabled: false
You have two problems that I can see immediately:
1: Your YAML configuration is referencing XYPage\HomePage, where the class's namespace is actually XYPage\Model\HomePage. I suspect this is actually an error in your example rather than your actual project, since you say that the elemental editor is working in the CMS.
2: Your getControllerName() method is returning HomePageController::class which isn't imported in the class, so it will be resolving to the same namespace as the model (XYPage\Model\HomePageController). While this is the default/expected location for SiteTree controllers, overloading this code means it's all on you! Add use XYPage\Controller\HomePageController; to your class definition.
After a lot of debugging i found out what caused this some of that behavior. In my case one problem was that i used unclecheese/silverstripe-gridfield-betterbuttons with elemental.
The next Problem is a react error:

Magento: Limit text field size in product custom attribute to 80 characters

I have a problem by using the following tip from the magento forum:
Quote:
One option you could do is to add a backend model for this attribute.
In this model you could write your own beforeSave function that will
process the length of given value and trim it to be the desired
length. The class should extend Mage_Eav_Model_Entity_Attribute_Backend_Abstract
Code:
public function beforeSave($object) {
$attrCode = $this->getAttribute()->getAttributeCode();
if ($object->hasData($attrCode)) {
$object->setData($attrCode, substr($object->getData($attrCode),0,50));
}
return $this; }
My question now is: how and where do I implement this snippet?
I recently put it in /app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Default.php but it had no effect.
first at all, you'll never should place custom code into core files. This destroys your upgradabillity. Create your own custom modules under app/code/local. There you can create your model which extends from Mage_Eav_Model_Entity_Attribute_Backend_Abstract.
May this link helps you to create your module:
http://www.smashingmagazine.com/2012/03/01/basics-creating-magento-module/
Also you can use magerun (an cli tool for magento) to create a module: http://magerun.net/

Should one library call another or is it a task of controller in Codeigniter and in MVC in general

I have to make some design decision in my application using Codeigniter.
I have a method in controller that calls a library for creating PDF.
Also I have some class that takes a number as an argument and returns string (number verbally ).
I would like to know what is the bestr practice to pass data between all this class. Is this a task of controller to call all libraries (between step2 and step 3) and provide all prepared data to a model that will create PDF. Or is this a task of Model itself to transform provided raw data by loading and calling class that converts number to string.
What would be the best solution in terms of loose coupling and modularity and clarity of the code.
This is a controller:
class Payu extends CI_Controller
{
public function raport($task_id)
{
/* (step 1) Load necessarty models */
$this->load->model('MTasks');
$this->load->model('mpdfinvoice');
/* (step 2) task details from DB */
$task_details = $this->MTasks->getTaskDetails($task_id);
/* (step 3) create PDF that will be send */
$this->mpdfinvoice->pdf($task_details);
/* (step 4) compose an email with attached pdf */
$this->email->from($this->config->item('noreply_email'));
$this->email->to($task_details['email']);
$this->email->attach('invoiceJustCreated.pdf');
$this->email->subject('opłaciłes to zlecenie');
$message = 'some message goes here';
$this->email->message($message);
$this->email->send();
}
}
This is a model that creates PDF file (called by controller)
class mpdfinvoice extends CI_Model
{
public function pdf($task_details)
{
/* (step 1) load necesary library and helper */
$this->load->library(array('fpdf' ));
$this->load->helper('file');
/* (step 2) set PDF page configuration*/
$this->fpdf->AddPage();
$this->fpdf->AddFont('arialpl','','arialpl.php');
$this->fpdf->SetFont('arialpl','',16);
/* (step 3) show data on PDF page */
$this->fpdf->cell('','',$task_details['payment_amount'] ,1);
/* I want to have "payment amount" verbally here
So Should I load and call the convert class here or
should I have this data already prepared by the controller
and only output it ? */
}
}
Try to look at controllers in codeigniter as your data glue. A controller retrieves data from clients, standardizes it and triggers the appropriate actions (redirect, triggering libraries, views, models and helpers while using the data provided.)
In your case just use a controller to retreive the data from your models or userinput. Then pass it to a library that creates the pdf. If the pdf creation is succesfull return true to let te controller know its a succes. Create a flashdata succes message and redirect to a page that outputs a view:
User request: pdf/download
Controller Pdf triggers the download method
download triggers the models and pushes the data to a view
The view with its data will be returned into a variable
The $view variable will be pushed to a Pdf library
trigger pdf create
Pdf triggers pdf download (optional)
Controller triggers redirect to pdf/overview
I would suggest that the creation of the PDF or any other file and all the convertions between values to happen at the Model and then the Controller decide which data to fetch from the Model in order to pass it to the appropriate View and it will know how to display it.
Controllers should not be used to directly display(output) data or access database and do file creations.
Also Models should not ever be used to output data for any case.

How to paginate a grid with selected columns

In the Agile Toolkit Tutorial (Jobeet), I setup the quick data model (Page 3) and it looks nice with the CRUD test page. I tried to change a line of code in the test.php file. The problem is when I added the paginator, line of code, the data in the grid disappeared. Is this a limitation to the paginator class? Is there a quick way to get this custom grid paginated? Thanks.
Original Code displays method not defined error when adding addPaginator as shown below:
$this->add('CRUD')->setModel('Category');
//$this->add('CRUD')->setModel('Job');
$jobCRUD=$this->add('CRUD');
$jobCRUD->setModel('Job');
$jobCRUD->addPaginator(3); //This line causes an method not defined error
Modified code using setSource doesn't display an error but displays an empty grid:
class page_test extends Page {
function init(){
parent::init();
//$this->add('CRUD')->setModel('Category'); //Not needed for my example
$grid=$this->add('Grid');
//$grid->setModel('Job'); //Removed this to show custom columns
$grid->addColumn('id');
$grid->addColumn('type');
$grid->addColumn('position');
$grid->setSource('job');
$grid->addPaginator(3); //Added this to paginate the results (doesn't work & removes data)
}
}
Solution:
$this->add('CRUD')->setModel('Category');
//$this->add('CRUD')->setModel('Job');
$jobCRUD=$this->add('CRUD');
$jobCRUD->setModel('Job');
$jobCRUD->grid->addPaginator(3); // This fixed the paginator
Jobeet is for Agile Toolkit 4.1 and uses "setSource" which is obsolete.
I think if you replace setSource with setModel it should be OK.

Categories