How to create new wordpress widgets for my themes - wordpress-theming

How to create new wordpress widgets for my themes ?

If you want to create a widget. Navigate to your plugins folder and create a blank file named as “sample.php” in “Sample” folder..
Copy below code and paste in sample.php file.
<?php
/*
Plugin Name: Widget
Description: Widget Description
*/
// Creating the widget
// Create a class named as "sample_widget" that is a child class of "WP_Widget".
class sample_widget extends WP_Widget
{
//Constructor of class
public function __construct()
{
parent::__construct(
// Id of our widget.
'sample_widget',
// This is the widget name that will be visible to user
__('Sample Widget'),
// Description of our widget
array(
'description' => __('Description of our widget.')
));
}
// Creating widget front-end
// This is where the action happens
// Creating function named as "widget", receiving two parameters.
public function widget($args, $instance)
{
/*Getting and assigning our widget title to wordpress hook "widget_title"
and passing its value to "$title" */
$title = apply_filters('widget_title', $instance['title']);
// Area, that is before the widget is diplayed
echo $args['before_widget'];
// Checking "$title" is empty or not
if (!empty($title)) /* If "$title" is not empty, below code will execute.
$args['before_title'] -> Displaying content before our widget title
$title -> Display our widget title
$args['after_title'] -> Displaying content after our widget title */ {
echo $args['before_title'] . $title . $args['after_title'];
}
// Displaying text of our widget
echo __('Hello, this is our widget text!');
// Displaying content after our widget
echo $args['after_widget'];
}
// This function naming our widget title
public function form($instance)
{
// If title is already set.
if (isset($instance['title'])) {
// $title is getting already assigned title
$title = $instance['title'];
}
// Otherwise our default title will be "Widget title"
else {
$title = __('Widget title');
}
?>
<!-- These are the settings and user interface that an admin will see -->
<p>
<!-- Already set title will be displayed at the top of our widget in admin panel -->
<label for="<?php
echo $this->get_field_id('title');
?>"><?php
_e('Title:');
?></label>
<input class="widefat" id="<?php
echo $this->get_field_id('title');
?>" name="<?php
echo $this->get_field_name('title');
?>" type="text" value="<?php
echo esc_attr($title);
?>" />
</p>
<?php
}
// This function will replace old title with new title of our widget
public function update($new_instance, $old_instance)
{
$instance = array();
$instance['title'] = (!empty($new_instance['title'])) ? strip_tags($new_instance['title']) : '';
return $instance;
}
}
// Function to register and load our newly widget
function sample_widget_load()
{
// Registering our widget named as "sample_widget"
register_widget('sample_widget');
}
// Calling our newly created function named as "sample_widget_load" to register our widget
add_action('widgets_init', 'sample_widget_load');
?>

This is my favourite tutorial about that:
http://justintadlock.com/archives/2009/05/26/the-complete-guide-to-creating-widgets-in-wordpress-28
I'm using it as a base to all my widgets.
Basically, the widget is a plugin, but you extend the class WP_Widget. It's quite easy, just follow that tutorial.
Also this is helpful http://codex.wordpress.org/Widgets_API
Good luck!

This is more a question for google than stackoverflow. You'll find tons of tutorials and examples on the web.
Widget API on wordpress site:
http://codex.wordpress.org/Widgets_API
Example of tutorial:
http://justintadlock.com/archives/2009/05/26/the-complete-guide-to-creating-widgets-in-wordpress-28
Another one:
http://www.lonewolfdesigns.co.uk/create-wordpress-widgets/

Related

WooCommerce Add Extra Tabs - Single Product Page

The following is the code from WooCommerce to Add Extra Tabs:
My Question is, how to insert a video link, or an iframe in the tab content.
add_filter( 'woocommerce_product_tabs', 'woo_new_product_tab' );
function woo_new_product_tab( $tabs ) {
// Adds the new tab
$tabs['test_tab'] = array(
'title' => __( 'New Product Tab', 'woocommerce' ),
'priority' => 50,
'callback' => 'woo_new_product_tab_content'
);
return $tabs;
}
function woo_new_product_tab_content() {
// The new tab content
echo '<h2>New Product Tab</h2>';
echo '<p>Here\'s your tab content.</p>';
}
How to insert anchor text, or iframe inside "Tab Content"
Any Help would appreciated..
Cheers
If you just want to show a static video iframe in your tab content, then simply add iframe/video tag in your tab content callback function likes
function woo_new_product_tab_content() {
// The new tab content
echo '<h2>See the video</h2>';
echo '<div><iframe width="100%" height="315" src="paste your video link here" frameborder="0" allowfullscreen></iframe></div>'; }
Or if your wants dynamic video link for each product then you must have to store video link in respective product meta first. And then echo get_post_meta for video on above 'src' attr.

Yii2 add to head() and endBody()

In developing a site that can have multiple front-end themes, I am looking for a way to allow users on the back-end to manually inject code into the head and body. Two use cases are as follows:
Case 1 - Styles
In the back-end, the user selects a theme.
User likes the theme but would like to make links a different color.
Rather than copy and modify the theme, user can set custom code to execute at end of <head> tag.
Case 2 - Scripts
User wants to add custom JavaScript to end of document but requires an additional JavaScript library as well.
Rather than copy and modify the theme, user can set custom code to execute at and of <body> tag.
I understand that both of these specific cases could be accomplished (in part) with the use of registerCss and registerJs but those automatically wrap whatever is passed to them in <style> or <script> tags. I am hoping there is a way to just directly inject whatever is indicated directly into the head() or endBody() methods. The reason behind this is that I do not wish to limit what the user can inject (perhaps a script tag is needed in the head).
Currently, I am just storing the code-to-be-added in params then manually including them in each theme as follows:
<?php $this->endBody() ?>
<?= $this->params['theme_include_body_end'] ?>
This is undesirable as it can easily be forgotten when creating the theme. I would like to find a way to append my param value to the endBody() call automatically so whenever endBody() is called, my code is included (same for the head() call).
Yii2 already provide this functionality in View Class by using Block Widget
you need 2 simple steps:
1- (in required View file): in any given view
<?php $this->beginBlock('block1'); ?>
...content of block1...
<?php $this->endBlock(); ?>
...
<?php $this->beginBlock('block3'); ?>
...content of block3...
<?php $this->endBlock(); ?>
2- (in layout): define block name and its place in the layout page
...
<?php if (isset($this->blocks['block1'])): ?>
<?= $this->blocks['block1'] ?>
<?php else: ?>
... default content for block1 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block2'])): ?>
<?= $this->blocks['block2'] ?>
<?php else: ?>
... default content for block2 ...
<?php endif; ?>
...
<?php if (isset($this->blocks['block3'])): ?>
<?= $this->blocks['block3'] ?>
<?php else: ?>
... default content for block3 ...
<?php endif; ?>
...
Referance: Yii2 Guide
http://www.yiiframework.com/doc-2.0/guide-structure-views.html#using-blocks
I hope this will help someone. Thank you.
You can use own View component that overrides methods renderHeadHtml() and renderBodyEndHtml(). In these methods can be injected necessary code as you need:
namespace common/components;
class View extends \yii\web\View {
/**
* #var string Content that should be injected to end of `<head>` tag
*/
public $injectToHead = '';
/**
* #var string Content that should be injected to end of `<body>` tag
*/
public $injectToBodyEnd = '';
/**
* #inheritdoc
*/
protected function renderHeadHtml()
{
return parent::renderHeadHtml() . $this->injectToHead;
}
/**
* #inheritdoc
*/
protected function renderBodyEndHtml($ajaxMode)
{
return parent::renderBodyEndHtml(ajaxMode) . $this->injectToBodyEnd;
}
}
In config file:
// ...
'components' => [
// ...
'view' => [
'class' => '\common\components\View',
]
]
Somewhere in controller code:
\Yii::$app->view->injectToHead = '...';
\Yii::$app->view->injectToBodyEnd = '...';
Another, perhaps more simple alternative depending on your use case is to use the view events. You can inject different items at different parts of the page. For example:
Yii::$app->view->on(View::EVENT_END_BODY, function () {
echo date('Y-m-d');
});
You can read more here: https://www.yiiframework.com/doc/guide/2.0/en/structure-views#view-events

How to generate radio button with label tag completely outside input tag in yii2

Yii2 HTML::radio() helper generate html input tag with label tag around that input like this:
<label>
<input type="radio" name="abc" value="1"> Hello
</label>
But I need it like this:
<input type="radio" name="abc" value="1" id="radio1">
<label for "radio1">Hello</label>
Is it postible to custozime this inside radio helper ?
No, you can't. As you can see from yii\helper\BaseHtml class code, this nesting of tags comes from the source code of radio() method, without means of configuration by changing options.
What you need is override that method. It's really easy.
In the namespace app\helpers, create class Html. Put it into a new file named /Helpers/Html.php relative to your app root (if you've got Yii basic app), and put something like this inside:
namespace app\helpers;
use Yii;
use yii\helpers\BaseHtml;
class Html extends BaseHtml
{
public static function radio($name, $checked = false, $options = [])
{
$options['checked'] = (bool) $checked;
$value = array_key_exists('value', $options) ? $options['value'] : '1';
if (isset($options['uncheck'])) {
// add a hidden field so that if the radio button is not selected, it still submits a value
$hidden = static::hiddenInput($name, $options['uncheck']);
unset($options['uncheck']);
} else {
$hidden = '';
}
if (isset($options['label'])) {
$label = $options['label'];
$labelOptions = isset($options['labelOptions']) ? $options['labelOptions'] : [];
unset($options['label'], $options['labelOptions']);
$content = static::input('radio', $name, $value, $options);
$content .= static::label($label, null, $labelOptions);
return $hidden . $content;
} else {
return $hidden . static::input('radio', $name, $value, $options);
}
}
}
Explanation:
We've just copied the code of radio() method from yii\helpers\BaseHtml and changed the lines containing static::label() to separate output of static::input() from it;
Since both original and our custom classes extend yii\helpers\BaseHtml, and original yii\helpers\Html is not redefining none of BaseHtml methods, there will be no loss in logic for elements other than radio.
Namespace and class name shouldn't be exactly the same, but obviously they should just differ from yii\helpers\Html.
Just replace use yii\helpers\Html; with use app\helpers\Html; in your View code.
That's all!

Twig and CodeIgniter form rendering issue. Form is being displayed as a String and not the HTML form

My first time to use Twig template with CodeIgniter. I'm used to the default form functionality of the framework, but I was asked to try to render the form using Twig. I find the template engine to be nice and confusing at the same time. So that means, my controller would be very fat with code. But the main issue here is to render the form using twig.
Below is what I used to do when I want to render a form. View: TableSample.php
<?php
echo form_open("", array("name"=>"form_reg", "method"=>"post", "id"=>"form_reg"));
echo form_input("type"=>"text", "name"=>"fname", "value"=>set_value("fname"));
echo form_input("type"=>"text", "name"=>"lname", "value"=>set_value("lname"));
echo form_input("type"=>"text", "name"=>"emailaddress", "value"=>set_value("emailaddress"));
echo form_input("type"=>"submit", "name"=>"submit", "value"=>"Submit");
echo form_close();
?>
Controller: register.php
public function register (){
$this->load->view("TableSample");
if($this->input->post("submit")) {
/** retrieve input details, pass them as array to model, then redirect if registration is successful**/
}
}
But since I have to use Twig, things have been a little bit different.
public function register () {
$detail["form_open"] = form_open("", array("name"=>"form_reg", "method"=>"post", "id"=>"form_reg"));
$detail["form_input_name"] = form_input("type"=>"text", "name"=>"fname");
$detail["form_input_lname"] = form_input("type"=>"text", "name"=>"lname");
$detail["form_input_eadd"] = form_input("type"=>"text", "name"=>"email");
$detail["form_input_submit"] = form_input("type"=>"submit", "name"=>"submit", "value"=>"Submit");
$detail["form_close"] = form_close();
//codes for saving here
//call twig view
$this->twig->display("tableSample.html.twig", $detail);
}
tableSample.html.twig would be like this:
<html>
<head></head>
<body>
{{ form_open }} //will display form as a **String** and not THE **HTML** like this:
<form method="post" name="form_reg" id="form_reg"></form>
{{ form_close }}
</body>
</html>
I know I'm missing something, please point me to the right way of rendering this. Thank You!
ok, I think I got it. raw made it possible. Twig Raw Filter

How to print a group display individually from its content?

I'm using Zend Framework and Zend_Form to render my form. But as I found it hard to customize it, I decided to print elements individually.
Problem is, I don't know how to print individual elements inside a display group. I know how to print my display groups (fieldsets) but I need to add something inside it (like a <div class="spacer"></div> to cancel the float:left.
Is there any way to display the group only without its content so I can print them individually myself?
Thank you for your help.
What you are looking for is the 'ViewScript' decorator. It allows you to form your html in any way you need. Here is a simple example of how it works:
The form, a simple search form:
<?php
class Application_Form_Search extends Zend_Form
{
public function init() {
// create new element
$query = $this->createElement('text', 'query');
// element options
$query->setLabel('Search Keywords');
$query->setAttribs(array('placeholder' => 'Query String',
'size' => 27,
));
// add the element to the form
$this->addElement($query);
//build submit button
$submit = $this->createElement('submit', 'search');
$submit->setLabel('Search Site');
$this->addElement($submit);
}
}
Next is the 'partial' this is the decorator, here is where you build the html how you want it:
<article class="search">
<!-- I get the action and method from the form but they were added in the controller -->
<form action="<?php echo $this->element->getAction() ?>"
method="<?php echo $this->element->getMethod() ?>">
<table>
<tr>
<!-- renderLabel() renders the Label decorator for the element
<th><?php echo $this->element->query->renderLabel() ?></th>
</tr>
<tr>
<!-- renderViewHelper() renders the actual input element, all decorators can be accessed this way -->
<td><?php echo $this->element->query->renderViewHelper() ?></td>
</tr>
<tr>
<!-- this line renders the submit element as a whole -->
<td><?php echo $this->element->search ?></td>
</tr>
</table>
</form>
</article>
and finally the controller code:
public function preDispatch() {
//I put this in the preDispatch method because I use it for every action and have it assigned to a placeholder.
//initiate form
$searchForm = new Application_Form_Search();
//set form action
$searchForm->setAction('/index/display');
//set label for submit button
$searchForm->search->setLabel('Search Collection');
//I add the decorator partial here. The partial .phtml lives under /views/scripts
$searchForm->setDecorators(array(
array('ViewScript', array(
'viewScript' => '_searchForm.phtml'
))
));
//assign the search form to the layout place holder
//substitute $this->view->form = $form; for a normal action/view
$this->_helper->layout()->search = $searchForm;
}
display this form in your view script with the normal <?php $this->form ?>.
You can use this method for any form you want to build with Zend_Form. So adding any element to your own fieldset would be simple.