TYPO3 Extension: Generate a PDF - typo3

Im trying to make an extension with Kickstarter that overrides the normal rendering of the page, and renders a PDF file. For this im using FPDF. But im not sure how to do it. I tried doing this, but it didnt work:
<?php
// require_once(PATH_tslib . 'class.tslib_pibase.php');
class tx_ishurkunde_pi1 extends tslib_pibase {
public $prefixId = 'tx_ishurkunde_pi1';
public $scriptRelPath = 'pi1/class.tx_ishurkunde_pi1.php';
public $extKey = 'ish_urkunde';
public $pi_checkCHash = TRUE;
public function main($content, array $conf) {
if (!t3lib_extMgm::isLoaded('fpdf')) return "Error!";
$pdf = new FPDF();
$pdf->AddPage();
$content = $pdf->Output('', 'S');
return $content;
}
}
?>
It still keeps rendering the normal web template. What am I missing?
FYI, Im not trying to render the HTML as PDF. Im trying to generate a PDF from scratch, using the URL parameters are text variables.

As far as I understood, your aim is to render a PDF instead of page elements.
Your current approach will not work since you are inserting a plugin onto the page. The plugin's return value is then given back to the TYPO3 content parser, and if the page has finished parsing, it is displayed. There is no part in it where you can throw over the whole page rendering; At least it is not intended to do, and you shouldn't to (albeit there are extensions that do this).
The eID approach would be to either create an eID script (have a look at dd_googlesitemap) which is called via GET param and renders only what you need. There you basically can do everything you want to.
In your extension's ext_localconf.php you register the eID script, like this:
$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include'][$_EXTKEY] = "EXT:{$_EXTKEY}/path/to/my/EIDHandler.php";
An Example eID handler structure:
class Tx_MyExt_EIDHandler
{
public function main()
{
// Your code here
}
}
$output = t3lib_div::makeInstance('Tx_MyExt_EIDHandler');
$output->main();
To call your eID script in the frontend, you append the appropriate GET params, like http://example.com/index.php?eID=tx_myext. This is the array key you defined in your ext_localconf.php (in my example, it is $_EXTKEY, but it can basically be any string).
The plugin/typoscript approach would be like e.g. TemplaVoila does it: You create a PAGE type and call a user_func which does your things. This would be the fastest approach because you already have a plugin. Important is that you render your own page type with only your plugin in it.
Example TypoScript:
specialPage = PAGE
specialPage {
type = 2
10 = USER
10.userFunc = tx_myextension_pi1->myFunc
}
After that, you can call your new page with http://example.com/index.php?type=2. However, headers etc are still rendered and you may need to remove them.

Related

Retrieve content element field from within a plugin template?

I am modifying the template of a plugin, and I want to retrieve a field from the content element.
Using f:debug I see the only data available is from the plugin itself, and none from the content element.
Is there any way I can perhaps insert the field I need in the plugin settings?
eg. something like:
plugin.tx_plugin.settings {
contentUid = TEXT
contentUid.field = uid
}
The best way I can think of to do this is with a custom ViewHelper. Something like:
namespace MyVendor\MyExtension\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class ContentUidViewHelper extends AbstractViewHelper
{
public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
$configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
return $configurationManager->getContentObject()->data['uid'];
}
}
In your Fluid template:
<mynamespace:contentUid />
This will get the uid of the content element, but you can get any field this way. Just change the key of the data array to the field you need.
In the corresponding method (like the listAction or showAction) of the controller you can get the data of the content element in the following way:
$contentObject = $this->configurationManager->getContentObject();
$this->view->assign('contentObjectData', $contentObject->data);
As far as I know, you can't get to that data using typoscript, but I've never needed it anyway since I've been using the above code in the controller.
settings do not have stdWrap-type per default, but only string. So you can not use cObjects as values.
For one (or a few) settings, you could do the stdWrap-processing in your method/class yourself:
$settingsAsTypoScriptArray = $this->objectManager->get(TypoScriptService::class)->convertPlainArrayToTypoScriptArray($this->settings);
$contentObj = $this->configurationManager->getContentObject();
if ($contentObj === null) {
$contentObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
}
// now override the values in the settings array with the processed value
$contentUid = (int)$contentObj->stdWrap($settingsAsTypoScriptArray['contentUid'], $settingsAsTypoScriptArray['contentUid.']);
If you wanna have many settings to be stdWraped, have a look into EXT:news. Georg implemented an interesting concept via useStdWrap configuration.

Wordpress Plugins / Custom Class / get_option() / shortcode

I'm having an issue displaying information returned from a custom class defined within a plugin's files, when using a shortcode. I'll write up some mock files that showcase my issue.
/wp-content/plugins/my-plugin/classes/my_class.php
<?php
class People {
public $api_url = "https://www.external-service.com/api";
private $api_key;
function __construct($key = null) {
if $(key) {
$this->api_key = $key;
}
function get_response() {
$path = $this->api_url . "?my_api_token=" . $this->api_key;
}
}
?>
/wp-content/plugins/my-plugin/my-plugin.php
<?php
/**
* all of the wordpress plugin comments
* ...
*/
require "myplg_options.php";
require "myplg_shortcodes.php";
The options page and menu is generated from myplg_options; it is functioning correctly (including using get_option to retrieve the saved option (in this case, the api key).
/wp-content/plugins/my-plugin/myplg_shortcodes.php
<?php
require "classes/my_class.php";
$options = get_option('myplg_settings');
$myplg = new People($options['myplg_api_key']);
$response = $myplg->get_response();
function myplg_list_result(){
echo "the shortcode is working!";
var_dump($options, $myplg, $respnose);
}
add_shortcode('myplg_list', 'myplg_list_result');
?>
Testing externally from wordpress, the class works and everything is fine and dandy. The plugin's option page sets and retains the single option perfectly; the shortcode actually registers and is usable from within a WordPress page/portfolio/etc.
The issue I'm having is that using var_dump, all three of those variables are dumped as NULL.
After doing some homework, I was able to determine that moving the three variable declarations inside the shortcode makes it work. It would seem to me, however, that doing that is not the best workflow, as I'd need to re-grab the option, instantiate a new class, and call the class' function for every shortcode.
Is there a way around this?
As mentioned in the comment it's because variables are function scoped. You may be better off using a Closure.
<?php
require "classes/my_class.php";
$options = get_option('myplg_settings');
$myplg = new People($options['myplg_api_key']);
$response = $myplg->get_response();
add_shortcode('myplg_list', function() use ($options, $response, $myplg) {
echo "the shortcode is working!";
var_dump($options, $myplg, $respnose);
});

how do you get a variable from a post address in zendframework 1

I am still new to Zend Framework and confused about a few concepts.
I have built a POST form and attached a unique Id to the URL at the end of the form. I now want to collect that Id when the form is submitted but I am unclear how to do that
I will show you want I have done:
Below is the function that renders the form from my controller page to the view. You will note that I have fed into the parameter, for the form, a return Action address with the ID
$action = "{$this->view->baseUrl()}/sample-manager/process-price/{$sampleId}";
$this->view->Form = $model= $this->_model->createForm($action);
The function to receive the post is below. However, I want to collect the Id that should have come back with the post return values, but I have no idea where to find it or how to attach it.
public function processPriceAction()
{
$this->requirePost();
if($this->_model->processTieredPriceForm($this->view->form, $this->getRequest()->getPost()))
{
$this->_helper->FlashMessenger('Changes saved');
return $this->_redirect("/product-ecommerce/{$this->_model->getProduct()->id}");
}
else
{
return $this->render('index');
}
}
In summary, when a post is returned, does the return address come with the post in Zend Framework?
Could you not supply the id into the construction of the form and assign it to a hidden element? For example, in your controller:
$action = "{$this->view->baseUrl()}/sample-manager/process-price";
$this->view->Form = $model= $this->_model->createForm($action, $sampleId);
In your form model (not provided so best guess here):
$sampleId = new Zend_Form_Element_Hidden('sampleId');
$sampleId->setValue($sampleId);
$form->addElement($sampleId);
Then once the form is posted, you should be able to get the sample id in your controller in the standard way:
$sampleId = $this->getParam('sampleId');
The answer depends a bit on how your routing is setup. If you're using the default setup, after the action name the default route allows for key/value pairs of additional data. So, you might have more luck with a URL like this:
{$this->view->baseUrl()}/sample-manager/process-price/id/{$sampleId}
That'll put your sampleId in a named parameter called 'id', which you can access in your controller action with $this->_getParam('id').

Zend: Quick and succinct way of inserting custom HTML into a Zend_Form?

Is there some method that accepts inserting custom html without having to actually add form controls, even if they're hidden and making my html a decorator?
I'm looking for something like:
$this->addCustomElement( array(
'div',
'body' => '<p>inner text</p>'
) );
I need something short and quick, I don't want to create a new class or something overkill.
Well it's really as simple as this:
$note = new Zend_Form_Element('note');
$note->helper = 'formNote';
$note->setValue('<b>hi</b>');
$form->addElement($note);
But the problem is that when you submit the form, the form calls $note->isValid(), which overrides the value, so if there are errors with the form, the next time you display it, the custom HTML won't be shown. There are two easy ways to fix this, the first is to override isValid() in your Form class like this:
public function isValid($data)
{
$note = $this->note->getValue();
$valid = parent::isValid($data);
$this->note->setValue($note);
return $valid;
}
But personally I find this kinda hackish way, and prefer the second option. That is to write a very simple class (this should really be part of Zend itself, I have no idea why it isn't, since it includes a formNote view helper, but no element that uses it):
class My_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
public function isValid($value, $context = null) { return true; }
}
Then you just have to do:
$note = new My_Form_Element_Note('note');
$note->setValue('<b>hi</b>');
$form->addElement($note);
And everything will just work.
Other options include doing some black magic with decorators, but I really recommend you to not go down that path.
Also note the AnyMarkup Decorator.

Render action to HTML email in Zend Framework

I have an action which is rendering some content via a layout.
I actually want to send this output in an email. What is the best way to achieve this in the Zend Framework?
I know I need to use the Zend_Mail component to send the email, but I'm unclear about how to attach the output of my action to Zend_Mail.
I've done some reading on the ContextSwitch action helper, and I think that might be appropriate, but I'm still not convinced.
I'm still new to Zend Framework. I'm used to using techniques like output buffering to capture output, which I don't think is the correct way to do this in Zend.
From your controller:
// do this if you're not using the default layout
$this->_helper->layout()->disableLayout();
$this->view->data = $items;
$htmlString = $this->view->render('foo/bar.phtml');
If you're doing this from a class that's not an instance of Zend_Controller_Action, you may have to create an instance of a Zend_view first, to do this:
$view = new Zend_view();
// you have to explicitly define the path to the template you're using
$view->setScriptPath(array($pathToTemplate));
$view->data = $data;
$htmlString = $view->render('foo/bar.phtml');
public static function sendMail($data = array(), $template = ''){
$html = new Zend_View();
$html->setScriptPath(APPLICATION_PATH . '/modules/default/views');
// assign valeues
if(count($data['Assigni'])){
foreach($data['Assigni'] as $assign){
$html->assign($assign['key'], $assign['value']);
}
}
// create mail object
$mail = new Zend_Mail('utf-8');
// render view //'scripts/newsletter/emailtemplate.phtml'
$bodyText = $html->render($template);
$mail->addTo($data['To']);
$mail->setSubject($data['Subject']);
$mail->setFrom($data['From'], $data['FromName']);
$mail->setBodyHtml($bodyText);
$mail->send();
}
when you dispatch the action, you can catch the event in postDispatch() method of plugin, that you can dynamically add to the stack from desired action. In that you recieve the contents of response by
//in action
//...some php code
Zend_Controller_Front::getInstance()->registerPlugin(new My_Plugin());
//in plugin
$htmlCode = $this->_response->getBody();
I can't give you a super-detailed answer, but if you want the full output (including the layout), I think you want to write your email function as an Action helper, and insert it at the PostDispatch hook of the Zend_Controller_Action->dispatch() loop.
See http://nethands.de/download/zenddispatch_en.pdf for the full Zend Framework Dispatch Process Overview.
If you don't need the layout included in your email content, then you could do this at many points, including by the use of a context switch, as you mentioned.