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);
});
Related
In my ext I have singleAction method. I want to change template inside this method, because I have 2 templates for single action. Is it possible? If it impossible, how can I solve this problem? Maybe generate another action?
It's not that simple to set a template. the setTemplate and getTemplate don't exist in the View.
You could revert to a standaloneview implemtation, which supports the use of setTemplatePathAndFilename
(example copied from Ludwig)
/**
* Renders the fluid email template
* #param string $template
* #param array $assign
* #return string
*/
public function renderFluidTemplate($template, Array $assign = array()) {
$templatePath = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName('EXT:myextension/Resources/Private/Templates/' . $template);
$view = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Fluid\\View\\StandaloneView');
$view->setTemplatePathAndFilename($templatePath);
$view->assignMultiple($assign);
return $view->render();
}
echo renderFluidTemplate('mail.html', array('test' => 'This is a test!'));
You could also switch to a different template with typoscript.
plugin.tx_yourpluginname.view.templateRootPaths = EXT:extension_name/Resources/Private/CustomPath/Templates/
And this can be put into any typoscript condition you want.
The best way to handle this is simply to have a switch in the template of the action, loading a different partial. This way the whole flow of logic stays intact and it's immediately understandable for everyone who will have to edit your code later on.
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.
I have setup in my MVC site a Session variable to carry ids to be used on any subsequent pages.
In my controller, var_dumping the session shows its there with the correct values but when I pass said values to the view and trying to echo them there, it comes up blank.
Any pointers as to whats going on to cause them to not appear.
Please note, the view is a partial view, not the main one.
Bootstrap session related code:
protected function _initSession(){
Zend_Session::start();
$SessAuto2Auto = new Zend_Session_Namespace('SessAuto2Auto');
$SessAuto2Auto->cityIds = "1,2,3"; // Hard code values for testing purposes
$SessAuto2Auto->IndustryIds = "3,4"; // Hard code values for testing purposes
}
Controller related code : ProductController.php
public function indexAction()
{
// .. Unrelated code removed for brevity
$response = $this->getResponse();
$response->insert('sidebar', $this->view->render('sidebar.phtml'));
// This code is dumping the values correctly
echo('<pre>');
var_dump($this->sessionAuto2Auto);
echo('</pre>');
// .. Unrelated code removed for brevity
$this->view->filterCity = $this->sessionAuto2Auto['cityIds'];
$this->view->filterIndustryIds = $this->sessionAuto2Auto['IndustryIds'];
}
View partial : sidebar.phtml
<?php
// This code does NOT show the value, comes up blank
echo($this->filterCity);
?>
If you are calling sidebar.phtml using the partial helper, partials have their own variable scope, they can only access variables which are passed in to them. You need to either include your session variables in your partial helper call:
echo $this->partial('sidebar.phtml', array(
'filterCity' => $this->filterCity,
'filterIndustryIds' => $this->filterIndustryIds
)
or use render instead (which uses the same scope as the other view scripts):
<?=$this->render('sidebar.phtml')?>
Is it possible to remove the 'id' attribute that Zend Framework adds to every Form Element by default?
I've looked at the documentation but don't seem to be able to find an answer to this rather straight forward question.
Possible Solution
Is there any cleaner way to do it other than setOption?
$submit = new Zend_Form_Element_Submit('submit');
$submit->setRequired(FALSE)
->setIgnore(TRUE)
->setDecorators($this->elementDecorators)
->setOptions(array('id' => ''));
A solution would be to override Zend_View_Helper_Form with your own View Helper.
But sincerely, don't take too much attention to this id attribute in your form, you will sooner or later need this id (if you're using Javascript for example) and the performance gain (to render the page) is too tiny to be taken into consideration. It will even be a performance loss since you're going to override a Helper.
If your purpose is different and you want to do that anyway, you need to write you own View Helper as follow:
class My_View_Helper_Form extends Zend_View_Helper_FormElement
{
public function form($name, $attribs = null, $content = false)
{
$info = $this->_getInfo($name, $content, $attribs);
extract($info);
$xhtml = '<form'
. $this->_htmlAttribs($attribs)
. '>';
if (false !== $content) {
$xhtml .= $content
. '</form>';
}
return $xhtml;
}
}
Finally, you simply need to overload the default view helper using a plugin loader. Read the manual for more information about plugin loader.
I'm trying to add some functionality from a plugin I have made into a Wordpress theme but I am having little joy. The documentation doesn't really help me solve the problem so perhaps someone here can help.
I have a plugin in Wordpress that is activated and working fine. The class for this plugin has a function called generateHtml which I would like to access from a Wordpress Theme. But whatever I try, I cannot seem to access my plugin's code.
Can either give me a summary of what I need to do to get a theme accessing code from a plugin and/or point out there I am going wrong in my code:
Plugin:
<?php
/** Usual comments here **/
if (!class_exists("ImageRotator")) {
class ImageRotator {
private $uploadPath = '';
private $pluginPath = '';
private $options;
function __construct() {
$this->uploadPath = dirname(__file__).'\\uploads\\';
// add_shortcode('imagerotator', array(&$this, 'generateHtml'));
}
// Various functions for plugin
function generateHtml() {
echo '<p>Hello World</p>';
}
}
}
/**
* Create instance of image rotator
*/
$imageRotator = new ImageRotator();
/**
* Create actions & filters for Wordpress
*/
if (isset($imageRotator)) {
// Actions
add_action('admin_menu', array(&$imageRotator, 'createMenu'));
add_action('admin_init', array(&$imageRotator, 'registerSettings'));
add_action('imagerotator_show', array(&$imageRotator, 'generateHtml'));
}
Portion from theme header page:
<?php if (isset($imageRotator)) {
$imageRotator->generateHtml();
} else if (isset($ImageRotator)) {
print_r($ImageRotator);
} else {
echo '<p>Nope!</p>';
}
if (function_exists("imagerotator_show")) {
echo 'Function found';
} else {
echo 'Function NOT found';
}
?>
Currently all I ever see is "Nope" and "Function NOT found". Thanks for any input.
Lee,
For starters, "imagerotator_show" is not a function; it's the name of a type of action. When you use the add_action() function, Wordpress just adds your method to the list of functions/methods to call when a particular action is triggered. Thus your second test will always respond with 'Function NOT found'.
The most likely cause of the first problem is failing to declare the method you want to call as a public method. You're also making the code harder than it needs to be.
The best practice I've seen for declaring methods and registering hooks from a class looks something like this:
if ( ! class_exists( 'Foo' ) ):
class Foo {
function __construct() {
add_action( 'hook_name', array( &$this, 'my_hook_implementation' ) );
}
function my_hook_implementation() {
// does something
}
public function my_special_method() {
// does something else
}
}
if ( class_exists( 'Foo' ) ):
$MyFoo = new Foo();
This allows your class to keep all of its implementation details private. When you need to call my_special_method(), you do it as follows:
$MyFoo->my_special_method();
#andrew since I can't comment I thought I would answer your ancillary question. See:
http://net.tutsplus.com/tutorials/wordpress/create-wordpress-plugins-with-oop-techniques/
Where it is explained that when defining a callback function from an object you have to use the array function. It's basically saying get the function 'my_hook_implementation' from the object $this and use it as the callback parameter to the add action hook. It is because you defined the function within the scope of the object and you have to define the scope in order for PHP to know what function you are talking about. The scope being the object referred to by the variable $this.
You just need to use do_action() function, inside your theme.
If you want the function generateHtml to appears inside your header.php you just need to open the header.php file and paste <?php do_action('imagerotator_show'); ?> where you want and then your function will be called there.