I created a module with a Custom Widget. When logging into the admin, going to content->widgets, creating an instance, and setting that instance to appear on the homepage, the widget appears as expected.
I have removed this instance and am now trying to create the widget by going to content->pages, editing the homepage -> content section, and selecting insert widget. I created a new instance of the widget and added some additional text into the homepage -> content section.
When I load the homepage the widget does not appear, though the rest of the text does appear.
The block for the widget is being called ( I tested this with a var_dump and exit).
The template is not being rendered however.
Here is my Block:
<?php
namespace MyNamespace\Slider\Block\Widget;
use Magento\Framework\View\Element\Template;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Block\Product\Context;
class Slider extends Template
{
protected $_template = "Yamazaki_Slider::widget/slider.phtml";
/**
* #var CollectionFactory
*/
protected $_productCollectionFactory;
/**
* #var CollectionFactory
*/
protected $_imageHelper;
/**
* #param Context $context
* #param CollectionFactory $productCollectionFactory
*/
public function __construct(Context $context, CollectionFactory $productCollectionFactory)
{
$this->_imageHelper = $context->getImageHelper();
$this->_productCollectionFactory = $productCollectionFactory;
parent::__construct($context);
}
/**
* Retrieve featured products collection
*/
public function getProducts()
{
$collection = $this->_productCollectionFactory->create();
return $collection->addAttributeToSelect('*')->addAttributeToFilter('is_featured','1');
}
}
and my Template:
<?php $imageBlock = $block->getLayout()->createBlock('Magento\Catalog\Block\Product\ListProduct'); ?>
<?php foreach($this->getProducts() as $product): ?>
<?php $productImage = $imageBlock->getImage($product, 'product_page_image_large'); ?>
<?php echo $productImage->toHtml(); ?>
<?php endforeach ?>
The other files in my module are:
etc/widget.xml:
<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="yamazaki_slider" class="MyNamespace\Slider\Block\Widget\Slider">
<label translate="true">My Image Slider</label>
<description>My Image Slider</description>
</widget>
</widgets>
module.xml and registration.php.
I do not have a etc/layout.xml file as I have noticed some widget/modules contain. Do I need this, or any other files?
Also, If I "Hide the Editor" inside content->pages->edit->content I see:
<p>{{widget type="MyNamespace\Slider\Block\Widget\Slider"}}</p>`
If I replace this with
{{block class="MyNamespace\Slider\Block\Widget\Slider" template="widget/slider.phtml"}}
The Content appears as expected
I managed to get the Block to Render
I had to add implements \Magento\Widget\Block\BlockInterface to MyNamespace\Slider\Block\Widget\Slider.
I'm not sure why this rendered, prior to adding the implements, using the first approach and not the second.
Magento is seriously lacking documentation!
Related
Right now I am using a shortcode function add_shortcode in display contents in the wordpress site. Now I want to inject a code in the footer by not modify the theme or a child them, instead I will do it via plugin. I just do not know the correct function name to search in google. I always use add_shortcode because it will display on all pages. it is just a custom popup code by me but I have to place the code in the footer
I am not really sure what you are asking? Do you need to know how to actually write a plugin? If this is the case then there is plenty of tutorials covering this topic. Some good resources related to this:
https://developer.wordpress.org/plugins/
https://developer.wordpress.org/plugins/hooks/
https://developer.wordpress.org/reference/hooks/wp_footer/
Add good thing might be to check how an existing plugin which does this is structured, for instance:
https://wordpress.org/plugins/insert-headers-and-footers/#developers
Do add something in the footer on every page you would do something like this, this file should be added under the wp-content/plugins directory:
<?php
/**
* Plugin Name: Footer plugin
* Description: Adds text to footer
* Version: 1.0.0
* Requires at least: 3.0
* Tested up to: 6.0
* Author: Author
* Text Domain: footer-plugin
**/
class FooterPlugin
{
public function __construct()
{
// hook into wp_footer
add_action('wp_footer', [$this, 'addFooter']);
}
public function addFooter()
{
echo '<span>footer text</span>';
}
}
// initialize the plugin when everything is loaded
add_action('plugins_loaded', function () {
new FooterPlugin();
});
Another way of doing this would be to replace the content of the footer from the generated output for the page:
class FooterPlugin
{
/** #var string */
private $replacement = 'SOME TEXT';
public function __construct()
{
add_action('template_redirect', [$this, 'templateRedirect']);
}
/**
* #var string $content
**/
public function templateRedirect(string $content)
{
ob_start([$this, 'handleBuffer']);
}
/**
* Replace everything in the footer tag
* #param string $buffer
* #return string
**/
public function handleBuffer(string $buffer): string
{
return preg_replace('/(\<footer\s*.*\>)((.|\n)*)(\<\/footer\>)/', '$1' . $this->replacement . '$3', $buffer);
}
}
I have a simple server/client SOAP interaction with a Shop class (shop.php) commented like this:
<?php
/**
* Class Shop
* Objective: Handling my shop
*
* #author Me
*/
require_once('config.php');
include("product.php");
include("fruit.php");
class Shop{
/**
* Returns a string with family's products concatenated
*
* #param string $familyId
* #return string
*
*/
public static function getFamilyProducts($familyId){
Now I puy my WSDLDocument.php next to my class (all files are in the same folder), and write my WSDLgenerator.php:
<?php
require_once('shop.php');
require_once('WSDLDocument.php');
$url = "http://localhost/Shop/server.php";
$uri = "http://localhost/Shop";
$wsdl = new WSDLDocument( "Shop", $url, $uri );
echo $wsdl->saveXml();
?>
My server is serving flawlessly to my client but here it is anyway if you want to check:
<?php
require_once('shop.php');
$uri = 'http://localhost/Shop';
$server = new SoapServer(null, array('uri' => $uri));
$server -> setClass('Shop');
$server -> handle();
?>
When I access WSDLGenerator.php it is printing "Class Shop Objective: Handling my shop" but nothing more. Browser's inspector is getting the class name and that lines:
<wsdl:service name="Shop">
<wsdl:documentation>Class Shop Objective: Handling my shop
</wsdl:documentation>
...
There are some calls to Shop ("ShopPortType", "ShopBinding", "ShopPort") but there's no signal of my functions and its parameters...
I FOUND THE PROBLEM! If the function is public static the XML just won't show (don't know why but that's it). Just change them to public.
To write a custom piwik plugin I'm following tutorial : http://piwik.org/blog/2014/09/create-widget-introducing-piwik-platform/
How can I access the request data that piwik receives within the plugin ?
Sample widget from above link :
class Widgets extends \Piwik\Plugin\Widgets
{
/**
* Here you can define the category the widget belongs to. You can reuse any existing widget category or define your own category.
* #var string
*/
protected $category = 'ExampleCompany';
/**
* Here you can add one or multiple widgets. You can add a widget by calling the method "addWidget()" and pass the name of the widget as well as a method name that should be called to render the widget. The method can be defined either directly here in this widget class or in the controller in case you want to reuse the same action for instance in the menu etc.
*/
protected function init()
{
$this->addWidget('Example Widget Name', $method = 'myExampleWidget');
$this->addWidget('Example Widget 2', $method = 'myExampleWidget', $params = array('myparam' => 'myvalue'));
}
/**
* This method renders a widget as defined in "init()". It's on you how to generate the content of the widget. As long as you return a string everything is fine. You can use for instance a "Piwik\View" to render a twig template. In such a case don't forget to create a twig template (eg. myViewTemplate.twig) in the "templates" directory of your plugin.
*
* #return string
*/
public function myExampleWidget()
{
$view = new View('#MyWidgetPlugin/myViewTemplate');
return $view->render();
}
}
How to access within the plugin the data piwik receives for each visitor request such as the request header fields ?
Access to a variable with name 'imageId':
$imageId = Common::getRequestVar('imageId');
About headers:
Piwik provides a list of headers methods through a ProxyHeaders class.
For now there are only two public static methods, that could be potentially interesting for you:
ProxyHeaders::getProxyClientHeaders, working with
'HTTP_CF_CONNECTING_IP',
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
and ProxyHeaders::getProxyHostHeaders for
'HTTP_X_FORWARDED_HOST'
Both these methods call another one, which is private:
/**
* Get headers present in the HTTP request
*
* #param array $recognizedHeaders
* #return array HTTP headers
*/
private static function getHeaders($recognizedHeaders)
{
$headers = array();
foreach ($recognizedHeaders as $header) {
if (isset($_SERVER[$header])) {
$headers[] = $header;
}
}
return $headers;
}
Because method getHeaders is private and it actually doesn't do what you want, probably the easiest way would be just to read headers directly from $_SERVER.
It will work this way: if you have a header with name "my-test-header" and value "123":
$_SERVER['HTTP_MY_TEST_HEADER'] // returns "123"
"Content-Type" => 'application/x-www-form-urlencoded'
$_SERVER['HTTP_CONTENT_TYPE'] // returns "application/x-www-form-urlencoded"
etc.
One note about web servers, whether it's Apache or Nginx or any other one, the configuration really matters here, especially for a HTTP_X_FORWARDED_FOR header.
I have designed a template using the template library of codeigniter, the template has the following regions:
$template['template_ar']['template'] = 'template_ar';
$template['template_ar']['regions'] = array(
'header',
'title',
'content',
'topcontent',
'sidebar',
'footer',
'options',
'script',
);
I used the following code to render my template
class faq extends MY_Controller {
/**
* Index
* This function views the Home Page
*
* #access public
* #return
*/
public function index() {
$this->template->write_view('content','comment/questions');
$this->template->write('options','You one',TRUE);
$this->template->render();
}
}
The problem that I want to eliminate is that I want to prevent the top content from appearing in my template. I need only the content, the header and the footer. Can anyone tell me how to do this?
Template Library for CodeIgniter
Set regions for writing to
$this->template->set_regions($regions);
Dynamically add region to the currently set template
$this->template->add_regions($name, $props);
Empty a region's content
$this->template->empty_region($name);
I am working on an Authentication Plugin using a Controller Plugin. I define my navigation config within the application.ini file, and then use that and the Database user records to dynamically load the ACL and apply it to Zend_Navigation. This bit works, as it successfully loads the menu and only displays the pages the user is allowed to see.
However, this doesn't stop the user from going to the page directly. What I want to do is identify when the user is going to a page they don't have access to within the Controller Plugin so I can redirect their request to the Authentication page.
I was thinking there must be a function to retrieve the current page from Zend_Navigation, but I can't find it... so maybe it doesn't exist.
Anyway, this is my full Controller Plugin. Anyone see a solution?
<?php
class Pog_Model_AuthPlugin extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $oRequest)
{
/**
* Load user
*/
$oAuth = Zend_Auth::getInstance();
$oDbUsers = new Pog_Model_DbTable_Users();
if (!$oAuth->hasIdentity())
{
$oUser = $oDbUsers->createRow();
$oUser->name = "guest";
$oUser->setReadOnly(true);
}
else
{
$oUser = $oAuth->getIdentity();
$oUser->setTable($oDbUsers);
}
/**
* Load ACL
*/
$oAcl = new Zend_Acl();
$oAcl->addRole($oUser->name);
/**
* Add current user privileges
*/
$oPrivileges = $oUser->getPrivileges();
foreach ($oPrivileges as $oPrivilege)
{
if (!$oAcl->has($oPrivilege->resource))
$oAcl->addResource($oPrivilege->resource);
$oAcl->allow($oUser->name, $oPrivilege->resource, $oPrivilege->privilege);
}
/**
* Load Navigation view helper
*/
$oViewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$oNavigation = $oViewRenderer->view->navigation();
/**
* Add remaining Navigation resources
*/
foreach ($oNavigation->getPages() as $oPage)
{
if (!is_null($oPage->getResource()) && !$oAcl->has($oPage->getResource()))
$oAcl->addResource($oPage->getResource());
}
/**
* Set ACL and Role
*/
$oNavigation->setAcl($oAcl)->setRole($oUser->name);
/**
* Check if use is allowed to be here
*/
...MAGIC GOES HERE...
}
}
I think that you should be able to get current navigation page as follows:
/**
* Load Navigation view helper
*/
$oViewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$oNavigation = $oViewRenderer->view->navigation();
/*#var $active array */
$active = $oNavigation->findActive($oNavigation->getContainer());
/*#var $activePage Zend_Navigation_Page_Mvc */
$activePage = $active['page'];
// example of getting page info
var_dump($activePage->getLabel(), $activePage->getController(), $activePage->getAction());
Hope this helps.
This is the solution I used, since I can't get Marcin's solution working in my setup for some reason.
I did some more thinking and thought of a nice simple solution to the problem. Rather than use the Navigation module to find the Active page, I find it myself. Since I am already iterating through the pages, it's a piece of cake to compare the Controller and Action - if these both match I have my Active page!
The new getPages() foreach loop looks like this:
$oCurrentPage = null;
foreach ($oNavigation->getPages() as $oPage)
{
/**
* Check for Current Page
*/
if ($oPage->getController() == $oRequest->getControllerName()
&& $oPage->getAction() == $oRequest->getActionName())
$oCurrentPage = $oPage;
/**
* Add Resource, if missing
*/
if (!is_null($oPage->getResource()) && !$oAcl->has($oPage->getResource()))
$oAcl->addResource($oPage->getResource());
}